diff --git a/Kits/ATGTK/CSVReader.h b/Kits/ATGTK/CSVReader.h new file mode 100644 index 0000000000000000000000000000000000000000..c0721effc8bc99d0dc1cc264ddd9401c254788b7 --- /dev/null +++ b/Kits/ATGTK/CSVReader.h @@ -0,0 +1,288 @@ +//-------------------------------------------------------------------------------------- +// File: CSVReader.h +// +// Simple parser for .csv (Comma-Separated Values) files. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + + +namespace DX +{ + class CSVReader + { + public: + enum class Encoding + { + ANSI, // File is ANSI (codepage 1252) + UTF16, // File is Unicode UTF-16 + UTF8, // File is Unicode UTF-8 + }; + + explicit CSVReader(_In_z_ const wchar_t* fileName, Encoding encoding = Encoding::ANSI, bool ignoreComments = false) : + m_end(nullptr), + m_currentChar(nullptr), + m_currentLine(0), + m_ignoreComments(ignoreComments) + { + assert(fileName != 0); + +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) + ScopedHandle hFile(safe_handle(CreateFile2(fileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(fileName, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + nullptr))); +#endif + if (!hFile) + { + throw std::exception("CreateFile"); + } + + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + throw std::exception("GetFileInformationByHandleEx"); + } + + if (fileInfo.EndOfFile.HighPart > 0 || fileInfo.EndOfFile.LowPart > 0x7ffffffd) + { + // File is 2 GBs or larger + throw std::exception("CSV too large"); + } + + std::unique_ptr data(new uint8_t[fileInfo.EndOfFile.LowPart + 2]); + + DWORD out; + if (!ReadFile(hFile.get(), data.get(), fileInfo.EndOfFile.LowPart, &out, nullptr) + || out != fileInfo.EndOfFile.LowPart) + { + throw std::exception("ReadFile"); + } + + // Ensure buffer is nul terminated + data[out] = data[out + 1] = '\0'; + + // Ignore lines in .csv that start with '#' character + + // Handle text encoding + if (encoding == Encoding::UTF16) + { + m_data.reset(reinterpret_cast(data.release())); + m_end = reinterpret_cast(&data[out]); + } + else + { + // If we are not UTF16, we have to convert... + UINT cp = (encoding == Encoding::UTF8) ? CP_UTF8 : 1252; + + int cch = ::MultiByteToWideChar(cp, 0, reinterpret_cast(data.get()), -1, nullptr, 0); + + if (cch <= 0) + { + throw std::exception("MultiByteToWideChar"); + } + + m_data.reset(new wchar_t[cch]); + + int result = ::MultiByteToWideChar(cp, 0, reinterpret_cast(data.get()), -1, m_data.get(), cch); + + if (result <= 0) + { + m_data.reset(); + throw std::exception("MultiByteToWideChar"); + } + + m_end = &m_data[result - 1]; + } + + // Locate the start of lines + bool newline = true; + for (const wchar_t* ptr = m_data.get(); *ptr != 0 && ptr < m_end; ) + { + if (*ptr == '\n' || *ptr == '\r') + { + ++ptr; + newline = true; + } + else if (*ptr == '#' && m_ignoreComments && newline) + { + // Skip to CR + for (; *ptr != 0 && *ptr != '\n' && ptr < m_end; ++ptr) {} + } + else if (*ptr == '"') + { + if (newline) + { + m_lines.push_back(ptr); + newline = false; + } + + // Skip to next " (skipping "" escapes) + for (ptr++; *ptr != 0 && ptr < m_end; ++ptr) + { + if (*ptr == '"') + { + ++ptr; + if (*ptr != '"') + break; + } + } + } + else if (newline) + { + m_lines.push_back(ptr); + newline = false; + ++ptr; + } + else + ++ptr; + } + + TopOfFile(); + } + + CSVReader(const CSVReader&) = delete; + CSVReader& operator=(const CSVReader&) = delete; + + // Return number of lines of data in CSV + size_t GetRecordCount() const { return m_lines.size(); } + + // Check for end of file + bool EndOfFile() const { return m_currentChar == nullptr; } + + // Return current record number (0-based) + size_t RecordIndex() const { return m_currentLine; } + + // Set to top of file + void TopOfFile() + { + m_currentChar = (m_lines.empty()) ? nullptr : m_lines[0]; + m_currentLine = 0; + } + + // Start processing next record (returns false when out of data) + bool NextRecord() + { + if (!m_currentChar) + return false; + + if (++m_currentLine >= m_lines.size()) + { + m_currentChar = nullptr; + return false; + } + + m_currentChar = m_lines[m_currentLine]; + + return true; + } + + // Get next item in record (returns false when reached end of record) + bool NextItem(_Out_writes_(maxstr) wchar_t* str, _In_ size_t maxstr) + { + if (!str || !m_currentChar || !maxstr) + return false; + + *str = L'\0'; + + const wchar_t* end = ((m_currentLine + 1) >= m_lines.size()) ? m_end : (m_lines[(m_currentLine + 1)]); + + if (m_currentChar >= end) + return false; + + wchar_t* dest = str; + wchar_t* edest = str + maxstr; + + for (const wchar_t* ptr = m_currentChar; ; ) + { + if (*ptr == 0 || ptr >= end || *ptr == '\n' || *ptr == '\r') + { + m_currentChar = end; + break; + } + else if (*ptr == ',') + { + m_currentChar = ptr + 1; + break; + } + else if (*ptr == '\t' || *ptr == ' ') + { + // Whitespace + ++ptr; + } + else if (*ptr == '"') + { + // Copy from " to ", respecting "" as double-quotes + for (ptr++; *ptr != 0 && ptr < end; ++ptr) + { + if (*ptr == '"') + { + ++ptr; + if (*ptr != '"') + break; + else if (dest < edest) + *(dest++) = '"'; + } + else if (dest < edest) + *(dest++) = *ptr; + } + } + else + { + for (; *ptr != 0 && ptr < end; ++ptr) + { + if (*ptr == '\n' || *ptr == '\r' || *ptr == ',') + break; + else if (dest < edest) + *(dest++) = *ptr; + } + } + } + + if (dest < edest) + *dest = 0; + + return true; + } + + template + bool NextItem(wchar_t(&name)[TNameLength]) + { + return NextItem(name, TNameLength); + } + + private: + struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } }; + + typedef std::unique_ptr ScopedHandle; + + inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } + + std::unique_ptr m_data; + const wchar_t* m_end; + const wchar_t* m_currentChar; + size_t m_currentLine; + bool m_ignoreComments; + std::vector m_lines; + }; +} diff --git a/Kits/ATGTK/CommandLineHelpers.cpp b/Kits/ATGTK/CommandLineHelpers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55b473a5a17ab61958eb684f7a0493b9d3b7e3a7 --- /dev/null +++ b/Kits/ATGTK/CommandLineHelpers.cpp @@ -0,0 +1,159 @@ +//-------------------------------------------------------------------------------------- +// CommandLineHelpers.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "CommandLineHelpers.h" +#include + +using namespace ATG; + +const wchar_t *ATG::ConsumeDigits(const wchar_t *value) +{ + if (value == nullptr) return nullptr; + const wchar_t *result = value; + + while (iswxdigit(*result)) + { + ++result; + } + + return result; +} + +#if defined(_XBOX_ONE) && defined(_TITLE) +ATG::WCRANGE ATG::MakeRange(wchar_t c0, wchar_t c1) +#else +WCRANGE ATG::MakeRange(wchar_t c0, wchar_t c1) +#endif +{ + uint32_t u0 = std::min(c0, c1); + uint32_t u1 = std::max(c0, c1); + uint32_t count = u1 - u0 + 1; + + WCRANGE result = { c0, wchar_t(std::min(count, uint32_t(0xFFFF))) }; + + return result; +} + +bool ATG::ParseCharacterRegion(const wchar_t *rangeSpec, std::vector ®ions) +{ + { + const wchar_t *charRange = rangeSpec; + + if (!*charRange) return false; + + wchar_t c0 = *charRange++; + if (!*charRange) + { + // Only one character specified -- but that's OK + WCRANGE range = { c0, 1 }; + regions.push_back(range); + return true; + } + + if (*charRange++ == '-') + { + wchar_t c1 = *charRange++; + if (!c1) + { + wprintf(L"Expected another character after '-' when parsing range\n"); + return false; + } + + if (*charRange) + { + wprintf(L"Unexpected character (%c) after parsing range\n", *charRange); + return false; + } + + regions.push_back(MakeRange(c0, c1)); + return true; + } + } + + { + const wchar_t *hexRange = rangeSpec; + + // Match and consume the hex prefix '0x' + if (_wcsnicmp(L"0x", hexRange, 2) != 0) + { + wprintf(L"Expected a hexidecimal range specification\n"); + return false; + } + hexRange += 2; + + unsigned c0 = 0; + // Scan the hex value + if (swscanf_s(hexRange, L"%lx", &c0) != 1) + { + wprintf(L"Expected a hexidecimal value following the prefix ('0x')\n"); + return false; + } + hexRange = ConsumeDigits(hexRange); + + if (c0 > 0xFFFF) + { + wprintf(L"The first hexidecimal value in the range specification is too large (0x%X)\n", c0); + return false; + } + + if (!*hexRange) + { + // Only one hex value specified -- but that's OK + WCRANGE range = { wchar_t(c0), 1 }; + regions.push_back(range); + return true; + } + + if (*hexRange++ == '-') + { + if (!*hexRange) + { + wprintf(L"Expected another hexidecimal value after '-' when parsing range\n"); + return false; + } + + // Match and consume the hex prefix '0x' + if (_wcsnicmp(L"0x", hexRange, 2) != 0) + { + wprintf(L"Second part of the hexidecimal range specification doesn't doesn't start with the '0x' hexidecimal prefix (%s)\n", hexRange); + return false; + } + hexRange += 2; + + unsigned c1 = 0; + // Scan the hex value + if (swscanf_s(hexRange, L"%lx", &c1) != 1) + { + wprintf(L"Expected a hexidecimal value following the prefix ('0x')\n"); + return false; + } + hexRange = ConsumeDigits(hexRange); + + if (c1 > 0xFFFF) + { + wprintf(L"The second hexidecimal value in the range specification is too large (0x%X)\n", c1); + return false; + } + + if (*hexRange) + { + wprintf(L"Unexpected character (%c) after parsing the second value in the range specification\n", *hexRange); + return false; + } + + regions.push_back(MakeRange(wchar_t(c0), wchar_t(c1))); + return true; + + } + else + { + wprintf(L"Expecting one or two hexidecimal values (4 digits or less) separated by a dash\n"); + return false; + } + } +} diff --git a/Kits/ATGTK/CommandLineHelpers.h b/Kits/ATGTK/CommandLineHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..0bca37f7ecc48d39bae789d99027567f1dd7864a --- /dev/null +++ b/Kits/ATGTK/CommandLineHelpers.h @@ -0,0 +1,96 @@ +//-------------------------------------------------------------------------------------- +// CommandLineHelpers.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include + +namespace ATG +{ + struct SValue + { + const wchar_t *name; + unsigned value; + }; + + + template + inline bool LookupByName(const wchar_t *name, const SValue(&table)[_SIZE], unsigned &result) + { + for (int i = 0; i < _SIZE; ++i) + { + if (!_wcsicmp(name, table[i].name)) + { + result = table[i].value; + return true; + } + } + return false; + } + + template + inline const wchar_t *LookupByValue(unsigned value, const SValue(&table)[_SIZE]) + { + for (int i = 0; i < _SIZE; ++i) + { + if (value == table[i].value) + return table[i].name; + } + + return L""; + } + + template + inline bool ParseTableValue(unsigned option, const wchar_t *name, const SValue(&table)[_SIZE], unsigned &result) + { + const wchar_t pleaseUseMsg[] = L"Please use one of the following: "; + + if (!LookupByName(name, table, result)) + { + wprintf(L"Invalid value specified with -%ls (%ls)\n", LookupByValue(option, g_Options), name); + wprintf(pleaseUseMsg); + PrintTable(_countof(pleaseUseMsg) - 1, table); + wprintf(L"\n\n"); + return false; + } + return true; + } + + template + inline void PrintTable(size_t indent, const SValue(&table)[_SIZE]) + { + size_t idt = indent; + for (int i = 0; i < _SIZE; ++i) + { + size_t cchName = wcslen(table[i].name); + + if (idt + cchName + 2 >= 80) + { + wprintf(L"\n"); + for (idt = 0; idt < indent; ++idt) wprintf(L" "); + } + + wprintf(L"%ls ", table[i].name); + idt += cchName + 2; + } + + wprintf(L"\n"); + } + + const wchar_t *ConsumeDigits(const wchar_t *value); + +#if defined(_XBOX_ONE) && defined(_TITLE) + typedef struct tagWCRANGE + { + WCHAR wcLow; + USHORT cGlyphs; +} WCRANGE, *PWCRANGE, FAR *LPWCRANGE; +#endif + WCRANGE MakeRange(wchar_t c0, wchar_t c1); + + bool ParseCharacterRegion(const wchar_t *rangeSpec, std::vector ®ions); + +} // namespace ATG diff --git a/Kits/ATGTK/FileHelpers.h b/Kits/ATGTK/FileHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..7e0a21abcc5ad449670f60750ea100aa47f0e52e --- /dev/null +++ b/Kits/ATGTK/FileHelpers.h @@ -0,0 +1,77 @@ +//-------------------------------------------------------------------------------------- +// FileHelpers.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include +#include + +#include + +namespace ATG +{ + class auto_delete_file + { + public: + auto_delete_file(HANDLE hFile) : m_handle(hFile) {} + + auto_delete_file(const auto_delete_file&) = delete; + auto_delete_file& operator=(const auto_delete_file&) = delete; + + ~auto_delete_file() + { + if (m_handle) + { + FILE_DISPOSITION_INFO info = {}; + info.DeleteFile = TRUE; + BOOL b = true; + b = SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, static_cast(sizeof(info))); +#ifdef _DEBUG + if (!b) + { + DWORD error = GetLastError(); + wchar_t buff[128] = {}; + swprintf_s(buff, L"ERROR: SetFileInformationByHandle failed (0x%08X)\n", error); + OutputDebugStringW(buff); + } +#endif + assert(b); + } + } + + void clear() { m_handle = 0; } + + private: + HANDLE m_handle; + }; + +#ifdef __IWICStream_FWD_DEFINED__ + class auto_delete_file_wic + { + public: + auto_delete_file_wic(Microsoft::WRL::ComPtr& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {} + + auto_delete_file_wic(const auto_delete_file_wic&) = delete; + auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete; + + ~auto_delete_file_wic() + { + if (m_filename) + { + m_handle.Reset(); + DeleteFileW(m_filename); + } + } + + void clear() { m_filename = 0; } + + private: + LPCWSTR m_filename; + Microsoft::WRL::ComPtr& m_handle; + }; +#endif +} \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/BufferDescriptor.cpp b/Kits/ATGTK/FrontPanel/BufferDescriptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..afad0726acce07fd9c3059c7434250eb394784ff --- /dev/null +++ b/Kits/ATGTK/FrontPanel/BufferDescriptor.cpp @@ -0,0 +1,23 @@ +//-------------------------------------------------------------------------------------- +// BufferDescriptor.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "BufferDescriptor.h" + +using namespace ATG; + + +void ATG::SetPixel(const BufferDesc & destBuffer, unsigned col, unsigned row, uint8_t clr) +{ + if (col >= destBuffer.width || row >= destBuffer.height) + return; + + unsigned index = row * (destBuffer.width) + col; + if (index < destBuffer.size) + { + destBuffer.data[index] = clr; + } +} \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/BufferDescriptor.h b/Kits/ATGTK/FrontPanel/BufferDescriptor.h new file mode 100644 index 0000000000000000000000000000000000000000..2d06381bd4ef255310fb6f54c34a3d08f002ff9d --- /dev/null +++ b/Kits/ATGTK/FrontPanel/BufferDescriptor.h @@ -0,0 +1,24 @@ +//-------------------------------------------------------------------------------------- +// BufferDescriptor.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include + + +namespace ATG +{ + struct BufferDesc + { + uint8_t *data; + size_t size; + unsigned width; + unsigned height; + }; + + void SetPixel(const BufferDesc &destBuffer, unsigned col, unsigned row, uint8_t clr); + +} // namespace ATG \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/CPUShapes.cpp b/Kits/ATGTK/FrontPanel/CPUShapes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4bc328b4b78a120393e46bdf7ef429e19311605e --- /dev/null +++ b/Kits/ATGTK/FrontPanel/CPUShapes.cpp @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------------------- +// CPUShapes.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "CPUShapes.h" +#include + +using namespace ATG; + +void CPUShapes::RenderRect(int left, int top, int width, int height, uint8_t color, bool filled) +{ + int right = left + width - 1; + int bottom = top + height - 1; + + int x_min = std::max(0, left); + int x_max = std::min(static_cast(m_bufferWidth) - 1, right); + for (int x = x_min; x <= x_max; x++) + { + int y_min = std::max(0, top); + int y_max = std::min(static_cast(m_bufferHeight) - 1, bottom); + for (int y = y_min; y <= y_max; y++) + { + if (filled || (x == left || x == right || y == top || y == bottom)) + { + m_buffer[y * m_bufferWidth + x] = color; + } + } + } +} + +void CPUShapes::RenderLine(int x, int y, LineOrientation orientation, int length, uint8_t color) +{ + switch (orientation) + { + case LineOrientation::Horizontal: + if (y >= 0 && y < static_cast(m_bufferHeight)) + { + int x_min = std::max(0, x); + int x_max = std::min(static_cast(m_bufferWidth) - 1, x + length - 1); + for (int column = x_min; column <= x_max; column++) + { + m_buffer[y * m_bufferWidth + column] = color; + } + } + break; + + + case LineOrientation::Vertical: + if (x >= 0 && x < static_cast(m_bufferWidth)) + { + int y_min = std::max(0, y); + int y_max = std::min(static_cast(m_bufferHeight) - 1, y + length - 1); + for (int row = y_min; row <= y_max; row++) + { + m_buffer[row * m_bufferWidth + x] = color; + } + } + break; + } +} + +void CPUShapes::RenderPoint(int x, int y, uint8_t color) +{ + if (x >= 0 && x < static_cast(m_bufferWidth) && y >= 0 && y < static_cast(m_bufferHeight)) + { + m_buffer[y * m_bufferWidth + x] = color; + } +} \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/CPUShapes.h b/Kits/ATGTK/FrontPanel/CPUShapes.h new file mode 100644 index 0000000000000000000000000000000000000000..ba522be59316456e1f42351b87a79afecc86a5e5 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/CPUShapes.h @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------------------- +// CPUShapes.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include + + +namespace ATG +{ + + class CPUShapes + { + public: + CPUShapes(unsigned int bufferWidth, unsigned int bufferHeight, uint8_t *buffer) + : m_bufferWidth(bufferWidth) + , m_bufferHeight(bufferHeight) + , m_buffer(buffer) + { + } + + enum class LineOrientation + { + Horizontal, + Vertical, + }; + + void RenderRect(int left, int top, int width, int height, uint8_t color = 0xFF, bool filled = true); + + void RenderLine(int x, int y, LineOrientation orientation, int length, uint8_t color = 0xFF); + + void RenderPoint(int x, int y, uint8_t color = 0xFF); + + private: + unsigned int m_bufferWidth; + unsigned int m_bufferHeight; + uint8_t *m_buffer; + }; + +} // namespace ATG \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp b/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f781e69e6427107ace0b22d754c18c33c488354 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/FrontPanelDisplay.cpp @@ -0,0 +1,488 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelDisplay.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "FrontPanelDisplay.h" + +#include + +#include "OSHelpers.h" +#include "FileHelpers.h" + +using namespace ATG; +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + // For more information, see DirectX Tool Kit's dds.h + const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#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_PITCH 0x00000008 // DDSD_PITCH +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE + +#pragma pack(push, 1) + struct DDS_PIXELFORMAT + { + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; + }; + + struct DDS_HEADER + { + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; + }; +#pragma pack(pop) + + const DDS_PIXELFORMAT DDSPF_L8 = { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; +} + +namespace DirectX +{ + // Reuse the WIC factory function from the DirectX Tool Kit. For implementation details, see WICTextureLoader.cpp +#ifdef __d3d12_x_h__ + extern IWICImagingFactory2* _GetWIC(); +#else + extern IWICImagingFactory* _GetWIC(); +#endif +} + +// -------------------------------------------------------------------------------- +// FrontPanelDisplay methods +// -------------------------------------------------------------------------------- +FrontPanelDisplay* FrontPanelDisplay::s_frontPanelDisplayInstance = nullptr; + +FrontPanelDisplay::FrontPanelDisplay(_In_ IXboxFrontPanelControl * frontPanelControl) + : m_frontPanelControl(frontPanelControl) + , m_displayWidth(0) + , m_displayHeight(0) +{ + if (s_frontPanelDisplayInstance) + { + throw std::exception("FrontPanelDisplay is a singleton"); + } + + s_frontPanelDisplayInstance = this; + + if (IsAvailable()) + { + uint32_t displayWidth = 0; + DX::ThrowIfFailed( + m_frontPanelControl->GetScreenWidth(&displayWidth) + ); + m_displayWidth = displayWidth; + + uint32_t displayHeight = 0; + DX::ThrowIfFailed( + m_frontPanelControl->GetScreenHeight(&displayHeight) + ); + m_displayHeight = displayHeight; + + m_buffer = std::make_unique(displayWidth * displayHeight); + } +} + +FrontPanelDisplay::~FrontPanelDisplay() +{ + s_frontPanelDisplayInstance = nullptr; +} + +void FrontPanelDisplay::Clear() +{ + if (IsAvailable()) + { + memset(m_buffer.get(), 0, m_displayWidth * m_displayHeight); + } +} + +void FrontPanelDisplay::Present() +{ + if (IsAvailable()) + { + m_frontPanelControl->PresentBuffer(m_displayWidth * m_displayHeight, m_buffer.get()); + } +} + +BufferDesc FrontPanelDisplay::GetBufferDescriptor() const +{ + BufferDesc result = {}; + result.data = m_buffer.get(); + result.size = m_displayWidth * m_displayHeight; + result.width = m_displayWidth; + result.height = m_displayHeight; + + return result; +} + +FrontPanelDisplay & FrontPanelDisplay::Get() +{ + if (!s_frontPanelDisplayInstance) + throw std::exception("FrontPanelDisplay is a singleton"); + + return *s_frontPanelDisplayInstance; +} + +void FrontPanelDisplay::SaveDDSToFile(_In_z_ const wchar_t * fileName) const +{ + if (!IsAvailable()) + { + return; + } + + if (!fileName) + { + throw std::invalid_argument("Invalid filename"); + } + + // Create file + ScopedHandle hFile(safe_handle(CreateFile2(fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr))); + + if (!hFile) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + auto_delete_file delonfail(hFile.get()); + + // Setup header + const size_t HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER); + uint8_t fileHeader[HEADER_SIZE] = {}; + + *reinterpret_cast(&fileHeader[0]) = DDS_MAGIC; + + auto header = reinterpret_cast(&fileHeader[0] + sizeof(uint32_t)); + header->size = sizeof(DDS_HEADER); + header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; + header->height = m_displayHeight; + header->width = m_displayWidth; + header->mipMapCount = 1; + header->caps = DDS_SURFACE_FLAGS_TEXTURE; + memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_L8, sizeof(DDS_PIXELFORMAT)); + + UINT rowPitch = m_displayWidth; + UINT imageSize = m_displayWidth * m_displayHeight; + + header->flags |= DDS_HEADER_FLAGS_PITCH; + header->pitchOrLinearSize = static_cast(rowPitch); + + // Write header & pixels + DWORD bytesWritten = 0; + if (!WriteFile(hFile.get(), fileHeader, static_cast(HEADER_SIZE), &bytesWritten, nullptr)) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + if (bytesWritten != HEADER_SIZE) + { + throw std::exception("WriteFile"); + } + + if (!WriteFile(hFile.get(), m_buffer.get(), static_cast(imageSize), &bytesWritten, nullptr)) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + if (bytesWritten != imageSize) + { + throw std::exception("WriteFile"); + } + + delonfail.clear(); +} + +void FrontPanelDisplay::SaveWICToFile(_In_z_ const wchar_t *filename, REFGUID guidContainerFormat) const +{ + if (!IsAvailable()) + { + return; + } + + if (!filename) + { + throw std::invalid_argument("Invalid filename"); + } + + auto pWIC = _GetWIC(); + if (!pWIC) + { + throw std::exception("_GetWIC"); + } + + ComPtr stream; + DX::ThrowIfFailed( + pWIC->CreateStream(stream.GetAddressOf()) + ); + + DX::ThrowIfFailed( + stream->InitializeFromFilename(filename, GENERIC_WRITE) + ); + + auto_delete_file_wic delonfail(stream, filename); + + ComPtr encoder; + DX::ThrowIfFailed( + pWIC->CreateEncoder(guidContainerFormat, 0, encoder.GetAddressOf()) + ); + + DX::ThrowIfFailed( + encoder->Initialize(stream.Get(), WICBitmapEncoderNoCache) + ); + + ComPtr frame; + DX::ThrowIfFailed( + encoder->CreateNewFrame(frame.GetAddressOf(), nullptr) + ); + + DX::ThrowIfFailed( + frame->Initialize(nullptr) + ); + + DX::ThrowIfFailed( + frame->SetSize(m_displayWidth, m_displayHeight) + ); + + DX::ThrowIfFailed( + frame->SetResolution(72, 72) + ); + + WICPixelFormatGUID targetGuid = GUID_WICPixelFormat8bppGray; + DX::ThrowIfFailed( + frame->SetPixelFormat(&targetGuid) + ); + + UINT rowPitch = m_displayWidth; + UINT imageSize = m_displayWidth * m_displayHeight; + + if (memcmp(&targetGuid, &GUID_WICPixelFormat8bppGray, sizeof(WICPixelFormatGUID)) != 0) + { + // Conversion required to write + ComPtr source; + DX::ThrowIfFailed( + pWIC->CreateBitmapFromMemory(m_displayWidth, m_displayHeight, GUID_WICPixelFormat8bppGray, + rowPitch, imageSize, + reinterpret_cast(m_buffer.get()), source.GetAddressOf()) + ); + + ComPtr FC; + DX::ThrowIfFailed( + pWIC->CreateFormatConverter(FC.GetAddressOf()) + ); + + BOOL canConvert = FALSE; + DX::ThrowIfFailed( + FC->CanConvert(GUID_WICPixelFormat8bppGray, targetGuid, &canConvert) + ); + + if (!canConvert) + { + throw std::exception("CanConvert"); + } + + DX::ThrowIfFailed( + FC->Initialize(source.Get(), targetGuid, WICBitmapDitherTypeNone, nullptr, 0, WICBitmapPaletteTypeFixedGray16) + ); + + WICRect rect = { 0, 0, static_cast(m_displayWidth), static_cast(m_displayHeight) }; + DX::ThrowIfFailed( + frame->WriteSource(FC.Get(), &rect) + ); + } + else + { + DX::ThrowIfFailed( + frame->WritePixels( + m_displayHeight, + rowPitch, imageSize, + reinterpret_cast(m_buffer.get())) + ); + } + + DX::ThrowIfFailed( + frame->Commit() + ); + + DX::ThrowIfFailed( + encoder->Commit() + ); + + delonfail.clear(); +} + +BufferDesc FrontPanelDisplay::LoadWICFromFile(_In_z_ const wchar_t* filename, std::unique_ptr& data, unsigned int frameindex) +{ + data.reset(); + + if (!filename) + { + throw std::invalid_argument("Invalid filename"); + } + + BufferDesc result = {}; + if (!IsAvailable()) + { + return result; + } + + auto pWIC = _GetWIC(); + if (!pWIC) + { + throw std::exception("_GetWIC"); + } + + ComPtr decoder; + DX::ThrowIfFailed( + pWIC->CreateDecoderFromFilename(filename, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()) + ); + + UINT frameCount = 0; + DX::ThrowIfFailed( + decoder->GetFrameCount(&frameCount) + ); + + if (frameindex >= frameCount) + { + throw std::out_of_range("Frame index invalid"); + } + + ComPtr frame; + DX::ThrowIfFailed( + decoder->GetFrame(frameindex, frame.GetAddressOf()) + ); + + UINT width, height; + DX::ThrowIfFailed( + frame->GetSize(&width, &height) + ); + + WICPixelFormatGUID pixelFormat; + DX::ThrowIfFailed( + frame->GetPixelFormat(&pixelFormat) + ); + + UINT rowPitch = m_displayWidth; + UINT imageSize = m_displayWidth * m_displayHeight; + + // Load image data + data.reset(new uint8_t[imageSize]); + + if (memcmp(&GUID_WICPixelFormat8bppGray, &pixelFormat, sizeof(GUID)) == 0 + && m_displayWidth == width + && m_displayHeight == height) + { + // No format conversion or resize needed + DX::ThrowIfFailed( + frame->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), data.get()) + ); + } + else if (m_displayWidth != width || m_displayHeight != height) + { + // Resize + ComPtr scaler; + DX::ThrowIfFailed( + pWIC->CreateBitmapScaler(scaler.GetAddressOf()) + ); + + DX::ThrowIfFailed( + scaler->Initialize(frame.Get(), m_displayWidth, m_displayHeight, WICBitmapInterpolationModeFant) + ); + + WICPixelFormatGUID pfScaler; + DX::ThrowIfFailed( + scaler->GetPixelFormat(&pfScaler) + ); + + if (memcmp(&GUID_WICPixelFormat8bppGray, &pfScaler, sizeof(GUID)) == 0) + { + // No format conversion needed + DX::ThrowIfFailed( + scaler->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), data.get()) + ); + } + else + { + ComPtr FC; + DX::ThrowIfFailed( + pWIC->CreateFormatConverter(FC.GetAddressOf()) + ); + + BOOL canConvert = FALSE; + DX::ThrowIfFailed( + FC->CanConvert(pfScaler, GUID_WICPixelFormat8bppGray, &canConvert) + ); + + if (!canConvert) + { + throw std::exception("CanConvert"); + } + + DX::ThrowIfFailed( + FC->Initialize(scaler.Get(), GUID_WICPixelFormat8bppGray, + WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut) + ); + + DX::ThrowIfFailed( + FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), data.get()) + ); + } + } + else + { + // Format conversion but no resize + ComPtr FC; + DX::ThrowIfFailed( + pWIC->CreateFormatConverter(FC.GetAddressOf()) + ); + + BOOL canConvert = FALSE; + DX::ThrowIfFailed( + FC->CanConvert(pixelFormat, GUID_WICPixelFormat8bppGray, &canConvert) + ); + + if (!canConvert) + { + throw std::exception("CanConvert"); + } + + DX::ThrowIfFailed( + FC->Initialize(frame.Get(), GUID_WICPixelFormat8bppGray, + WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut) + ); + + DX::ThrowIfFailed( + FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), data.get()) + ); + } + + result.data = data.get(); + result.size = imageSize; + result.width = m_displayWidth; + result.height = m_displayHeight; + return result; +} \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/FrontPanelDisplay.h b/Kits/ATGTK/FrontPanel/FrontPanelDisplay.h new file mode 100644 index 0000000000000000000000000000000000000000..78b224956d83250a084d9e49bb03e8f6e203192d --- /dev/null +++ b/Kits/ATGTK/FrontPanel/FrontPanelDisplay.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelDisplay.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This code requires the March 2017 XDK or later +#endif + +#include + +#include + +#include "BufferDescriptor.h" + + +namespace ATG +{ + class FrontPanelDisplay + { + public: + + FrontPanelDisplay(_In_ IXboxFrontPanelControl *frontPanelControl); + + FrontPanelDisplay(FrontPanelDisplay &&moveFrom) = default; + FrontPanelDisplay& operator=(FrontPanelDisplay &&moveFrom) = default; + + FrontPanelDisplay(FrontPanelDisplay const&) = delete; + FrontPanelDisplay& operator=(FrontPanelDisplay const&) = delete; + + virtual ~FrontPanelDisplay(); + + void Clear(); + + void Present(); + + // Low-level access to the buffer + unsigned int GetDisplayWidth() const { return m_displayWidth; } + unsigned int GetDisplayHeight() const { return m_displayHeight; } + + uint8_t *GetBuffer() const { return m_buffer.get(); } + + // Get a bufer descriptor + BufferDesc GetBufferDescriptor() const; + + // Capture the screen + void SaveDDSToFile(_In_z_ const wchar_t *filename) const; + void SaveWICToFile(_In_z_ const wchar_t *filename, REFGUID guidContainerFormat) const; + + // Loads a buffer from a file + BufferDesc LoadWICFromFile(_In_z_ const wchar_t* filename, std::unique_ptr& data, unsigned int frameindex = 0); + + // Determine whether the front panel is available + bool IsAvailable() const { return m_frontPanelControl; } + + // Singleton + static FrontPanelDisplay& Get(); + + private: + Microsoft::WRL::ComPtr m_frontPanelControl; + unsigned int m_displayWidth; + unsigned int m_displayHeight; + std::unique_ptr m_buffer; + + static FrontPanelDisplay *s_frontPanelDisplayInstance; + }; +} \ No newline at end of file diff --git a/Kits/ATGTK/FrontPanel/FrontPanelInput.cpp b/Kits/ATGTK/FrontPanel/FrontPanelInput.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c1e1a051bd2d24dec155317f59a8c105d193323 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/FrontPanelInput.cpp @@ -0,0 +1,187 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelInput.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "FrontPanelInput.h" + +#include + +using namespace ATG; + +using Microsoft::WRL::ComPtr; + +// -------------------------------------------------------------------------------- +// FrontPanelInput::Impl definition +// -------------------------------------------------------------------------------- +#pragma region FrontPanelInput::Impl definition +class FrontPanelInput::Impl +{ +public: + Impl(FrontPanelInput *owner, _In_ IXboxFrontPanelControl *frontPanelControl) + : mOwner(owner) + , mFrontPanelControl(frontPanelControl) + { + if (s_frontPanelInput) + { + throw std::exception("FrontPanelInput is a singleton"); + } + + s_frontPanelInput = this; + } + + ComPtr mFrontPanelControl; + FrontPanelInput *mOwner; + static FrontPanelInput::Impl *s_frontPanelInput; + + void GetState(State &state) + { + XBOX_FRONT_PANEL_BUTTONS buttonReading = {}; + if (IsAvailable()) + { + DX::ThrowIfFailed(mFrontPanelControl->GetButtonStates(&buttonReading)); + } + state.buttons.rawButtons = buttonReading; + + XBOX_FRONT_PANEL_LIGHTS lightReading = {}; + if (IsAvailable()) + { + DX::ThrowIfFailed(mFrontPanelControl->GetLightStates(&lightReading)); + } + state.lights.rawLights = lightReading; + + state.buttons.button1 = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_BUTTON1) == XBOX_FRONT_PANEL_BUTTONS_BUTTON1; + state.buttons.button2 = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_BUTTON2) == XBOX_FRONT_PANEL_BUTTONS_BUTTON2; + state.buttons.button3 = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_BUTTON3) == XBOX_FRONT_PANEL_BUTTONS_BUTTON3; + state.buttons.button4 = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_BUTTON4) == XBOX_FRONT_PANEL_BUTTONS_BUTTON4; + state.buttons.button5 = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_BUTTON5) == XBOX_FRONT_PANEL_BUTTONS_BUTTON5; + state.buttons.dpadLeft = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_LEFT) == XBOX_FRONT_PANEL_BUTTONS_LEFT; + state.buttons.dpadRight = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_RIGHT) == XBOX_FRONT_PANEL_BUTTONS_RIGHT; + state.buttons.dpadUp = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_UP) == XBOX_FRONT_PANEL_BUTTONS_UP; + state.buttons.dpadDown = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_DOWN) == XBOX_FRONT_PANEL_BUTTONS_DOWN; + state.buttons.buttonSelect = (buttonReading & XBOX_FRONT_PANEL_BUTTONS_SELECT) == XBOX_FRONT_PANEL_BUTTONS_SELECT; + + state.lights.light1 = (lightReading & XBOX_FRONT_PANEL_LIGHTS_LIGHT1) == XBOX_FRONT_PANEL_LIGHTS_LIGHT1; + state.lights.light2 = (lightReading & XBOX_FRONT_PANEL_LIGHTS_LIGHT2) == XBOX_FRONT_PANEL_LIGHTS_LIGHT2; + state.lights.light3 = (lightReading & XBOX_FRONT_PANEL_LIGHTS_LIGHT3) == XBOX_FRONT_PANEL_LIGHTS_LIGHT3; + state.lights.light4 = (lightReading & XBOX_FRONT_PANEL_LIGHTS_LIGHT4) == XBOX_FRONT_PANEL_LIGHTS_LIGHT4; + state.lights.light5 = (lightReading & XBOX_FRONT_PANEL_LIGHTS_LIGHT5) == XBOX_FRONT_PANEL_LIGHTS_LIGHT5; + } + + void SetLightStates(const XBOX_FRONT_PANEL_LIGHTS &lights) + { + if (IsAvailable()) + { + DX::ThrowIfFailed(mFrontPanelControl->SetLightStates(lights)); + } + } + + bool IsAvailable() const + { + return mFrontPanelControl; + } +}; + +FrontPanelInput::Impl* FrontPanelInput::Impl::s_frontPanelInput = nullptr; +#pragma endregion + +// -------------------------------------------------------------------------------- +// FrontPanelInput methods +// -------------------------------------------------------------------------------- +#pragma region FrontPanelInput methods +// Public constructor. +FrontPanelInput::FrontPanelInput(_In_ IXboxFrontPanelControl * frontPanelControl) + : pImpl( new Impl(this, frontPanelControl)) +{ +} + +// Move constructor. +FrontPanelInput::FrontPanelInput(FrontPanelInput && moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ + pImpl->mOwner = this; + pImpl->mFrontPanelControl = moveFrom.pImpl->mFrontPanelControl; + moveFrom.pImpl->mFrontPanelControl = nullptr; +} + +// Move assignment. +FrontPanelInput & FrontPanelInput::operator=(FrontPanelInput && moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + pImpl->mOwner = this; + pImpl->mFrontPanelControl = moveFrom.pImpl->mFrontPanelControl; + moveFrom.pImpl->mFrontPanelControl = nullptr; + return *this; +} + +FrontPanelInput::~FrontPanelInput() +{ +} + +FrontPanelInput::State FrontPanelInput::GetState() +{ + State state; + pImpl->GetState(state); + return state; +} + +void FrontPanelInput::SetLightStates(const XBOX_FRONT_PANEL_LIGHTS &lights) +{ + pImpl->SetLightStates(lights); +} + +FrontPanelInput & FrontPanelInput::Get() +{ + if (!Impl::s_frontPanelInput || !Impl::s_frontPanelInput->mOwner) + throw std::exception("FrontPanelInput is a singleton"); + + return *Impl::s_frontPanelInput->mOwner; +} + +bool FrontPanelInput::IsAvailable() const +{ + return pImpl->IsAvailable(); +} +#pragma endregion + +// -------------------------------------------------------------------------------- +// FrontPanelInput::ButtonStateTracker methods +// -------------------------------------------------------------------------------- +#pragma region FrontPanelInput::ButtonStateTracker methods + +#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.buttons.field ) | ( ( !!state.buttons.field ^ !!lastState.buttons.field ) << 1 ) ); + +void FrontPanelInput::ButtonStateTracker::Update(const State& state) +{ + buttonsChanged = !!(state.buttons.rawButtons ^ lastState.buttons.rawButtons); + + UPDATE_BUTTON_STATE(button1); + + assert((!state.buttons.button1 && !lastState.buttons.button1) == (button1 == UP)); + assert((state.buttons.button1 && lastState.buttons.button1) == (button1 == HELD)); + assert((!state.buttons.button1 && lastState.buttons.button1) == (button1 == RELEASED)); + assert((state.buttons.button1 && !lastState.buttons.button1) == (button1 == PRESSED)); + + UPDATE_BUTTON_STATE(button2); + UPDATE_BUTTON_STATE(button3); + UPDATE_BUTTON_STATE(button4); + UPDATE_BUTTON_STATE(button5); + UPDATE_BUTTON_STATE(dpadLeft); + UPDATE_BUTTON_STATE(dpadRight); + UPDATE_BUTTON_STATE(dpadUp); + UPDATE_BUTTON_STATE(dpadDown); + UPDATE_BUTTON_STATE(buttonSelect); + + lastState = state; +} + +#undef UPDATE_BUTTON_STATE + +void FrontPanelInput::ButtonStateTracker::Reset() +{ + memset(this, 0, sizeof(ButtonStateTracker)); +} +#pragma endregion diff --git a/Kits/ATGTK/FrontPanel/FrontPanelInput.h b/Kits/ATGTK/FrontPanel/FrontPanelInput.h new file mode 100644 index 0000000000000000000000000000000000000000..fbc1cdcc9b0aeddc4e2d67169bbf5f7d46a05a00 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/FrontPanelInput.h @@ -0,0 +1,117 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelInput.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This code requires the March 2017 XDK or later +#endif + +#include + +struct IXboxFrontPanelControl; +enum XBOX_FRONT_PANEL_LIGHTS; + +namespace ATG +{ + class FrontPanelInput + { + public: + FrontPanelInput(_In_ IXboxFrontPanelControl *frontPanelControl); + + FrontPanelInput(FrontPanelInput &&moveFrom); + FrontPanelInput& operator=(FrontPanelInput &&moveFrom); + + FrontPanelInput(FrontPanelInput const&) = delete; + FrontPanelInput& operator=(FrontPanelInput const&) = delete; + + virtual ~FrontPanelInput(); + + struct Buttons + { + bool button1; + bool button2; + bool button3; + bool button4; + bool button5; + bool dpadLeft; + bool dpadRight; + bool dpadUp; + bool dpadDown; + bool buttonSelect; + uint32_t rawButtons; + }; + + struct Lights + { + bool light1; + bool light2; + bool light3; + bool light4; + bool light5; + uint32_t rawLights; + }; + + struct State + { + Buttons buttons; + Lights lights; + }; + + class ButtonStateTracker + { + public: + enum ButtonState + { + UP = 0, // Button is up + HELD = 1, // Button is held down + RELEASED = 2, // Button was just released + PRESSED = 3, // Buton was just pressed + }; + + ButtonState button1; + ButtonState button2; + ButtonState button3; + ButtonState button4; + ButtonState button5; + ButtonState dpadLeft; + ButtonState dpadRight; + ButtonState dpadUp; + ButtonState dpadDown; + ButtonState buttonSelect; + bool buttonsChanged; + + ButtonStateTracker() { Reset(); } + + void Update(const State& state); + + void Reset(); + + State GetLastState() const { return lastState; } + + private: + State lastState; + }; + + // Retrieve the current state of the FrontPanel buttons + State GetState(); + + // Set the lights on the FrontPanel + void SetLightStates(const XBOX_FRONT_PANEL_LIGHTS &lights); + + // Singleton + static FrontPanelInput& Get(); + + // Determine whether the front panel is available + bool IsAvailable() const; + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} // namespace ATG diff --git a/Kits/ATGTK/FrontPanel/FrontPanelRenderTarget.cpp b/Kits/ATGTK/FrontPanel/FrontPanelRenderTarget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bcb84480d2743cb723988a07addb53db510cd95 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/FrontPanelRenderTarget.cpp @@ -0,0 +1,168 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelRenderTarget.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "FrontPanelRenderTarget.h" +#include "DirectXHelpers.h" + +#include + +using Microsoft::WRL::ComPtr; + +using namespace ATG; +using namespace DirectX; + +FrontPanelRenderTarget::FrontPanelRenderTarget() + : m_displayWidth(0), + m_displayHeight(0), + m_renderTargetFormat(DXGI_FORMAT_UNKNOWN) +{ +} + +FrontPanelRenderTarget::~FrontPanelRenderTarget() +{ +} + +void FrontPanelRenderTarget::CreateDeviceDependentResources(_In_ IXboxFrontPanelControl *frontPanelControl, _In_ ID3D11Device *device) +{ + m_frontPanelControl = frontPanelControl; + + // Determine the render target size in pixels + DX::ThrowIfFailed(m_frontPanelControl->GetScreenWidth(&m_displayWidth)); + DX::ThrowIfFailed(m_frontPanelControl->GetScreenHeight(&m_displayHeight)); + + // Get the render target format for the Front Panel + DX::ThrowIfFailed(m_frontPanelControl->GetScreenPixelFormat(&m_renderTargetFormat)); + + // Create memory blt buffer + m_buffer.reset(new uint8_t[m_displayWidth * m_displayHeight]); + + // Create staging blt buffer + { + CD3D11_TEXTURE2D_DESC desc( + m_renderTargetFormat, + m_displayWidth, + m_displayHeight, + 1, // The render target view has only one texture. + 1, // Use a single mipmap level. + 0, + D3D11_USAGE_STAGING, + D3D11_CPU_ACCESS_READ + ); + + DX::ThrowIfFailed( + device->CreateTexture2D( &desc, 0, m_staging.ReleaseAndGetAddressOf()) + ); + + SetDebugObjectName(m_staging.Get(), "FrontPanel Staging"); + } + + // Create the render target + { + CD3D11_TEXTURE2D_DESC desc( + m_renderTargetFormat, + m_displayWidth, + m_displayHeight, + 1, // The render target view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + D3D11_USAGE_DEFAULT, + 0 + ); + + DX::ThrowIfFailed( + device->CreateTexture2D(&desc, nullptr, m_renderTarget.ReleaseAndGetAddressOf()) + ); + + SetDebugObjectName(m_renderTarget.Get(), "FrontPanel RT"); + } + + // Create the render target view + { + CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2D, m_renderTargetFormat); + + DX::ThrowIfFailed(device->CreateRenderTargetView( + m_renderTarget.Get(), + &renderTargetViewDesc, + m_renderTargetView.ReleaseAndGetAddressOf() + )); + + SetDebugObjectName(m_renderTargetView.Get(), "FrontPanel RTV"); + } + + // Create the monochrome post-processor + m_panelBlt = std::make_unique (device); +} + +void FrontPanelRenderTarget::Clear(_In_ ID3D11DeviceContext * context, const float ColorRGBA[4]) +{ + context->ClearRenderTargetView(m_renderTargetView.Get(), ColorRGBA); +} + +void FrontPanelRenderTarget::SetAsRenderTarget(_In_ ID3D11DeviceContext * context) +{ + auto renderTargetView = m_renderTargetView.Get(); + context->OMSetRenderTargets(1, &renderTargetView, nullptr); +} + +void FrontPanelRenderTarget::GPUBlit(_In_ ID3D11DeviceContext * context, _In_ ID3D11ShaderResourceView * srcSRV) +{ + assert(m_panelBlt); + + SetAsRenderTarget(context); + + // Set the viewports for the off-screen render target + D3D11_VIEWPORT viewport = { 0.0f, 0.0f, float(m_displayWidth), float(m_displayHeight), 0.0f, 1.0f }; + context->RSSetViewports(1, &viewport); + + // Convert pixels from srcSRV to grayscale + m_panelBlt->SetSourceTexture(srcSRV); + m_panelBlt->Process(context); + context->Flush(); + + ID3D11ShaderResourceView* srv = nullptr; + context->PSSetShaderResources(0, 1, &srv); +} + +void FrontPanelRenderTarget::CopyToBuffer(_In_ ID3D11DeviceContext * context, BufferDesc &desc) +{ + assert(m_staging && m_renderTarget); + context->CopyResource(m_staging.Get(), m_renderTarget.Get()); + + MapGuard mapped(context, m_staging.Get(), 0, D3D11_MAP_READ, 0); + + auto sptr = reinterpret_cast(mapped.pData); + uint8_t *dptr = desc.data; + + unsigned width = std::min(desc.width, mapped.RowPitch); + unsigned height = std::min(desc.height, m_displayHeight); + + for (size_t h = 0; h < height; ++h) + { + memcpy_s(dptr, width, sptr, mapped.RowPitch); + sptr += mapped.RowPitch; + dptr += desc.width; + } +} + +void FrontPanelRenderTarget::PresentToFrontPanel(_In_ ID3D11DeviceContext *context) +{ + assert(m_frontPanelControl); + + unsigned bufSize = m_displayWidth * m_displayHeight; + + BufferDesc desc; + desc.data = m_buffer.get(); + desc.size = bufSize; + desc.width = m_displayWidth; + desc.height = m_displayHeight; + + CopyToBuffer(context, desc); + + m_frontPanelControl->PresentBuffer(bufSize, m_buffer.get()); +} diff --git a/Kits/ATGTK/FrontPanel/FrontPanelRenderTarget.h b/Kits/ATGTK/FrontPanel/FrontPanelRenderTarget.h new file mode 100644 index 0000000000000000000000000000000000000000..6c64584e667dd71703a0c6dab0b7ecaa97878ce1 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/FrontPanelRenderTarget.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelRenderTarget.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This code requires the March 2017 XDK or later +#endif + +#include + +#include "BufferDescriptor.h" +#include "PostProcess.h" + + +namespace ATG +{ + class FrontPanelRenderTarget + { + public: + FrontPanelRenderTarget(); + virtual ~FrontPanelRenderTarget(); + + FrontPanelRenderTarget(FrontPanelRenderTarget&&) = default; + FrontPanelRenderTarget& operator=(FrontPanelRenderTarget&&) = default; + + FrontPanelRenderTarget(const FrontPanelRenderTarget&) = delete; + FrontPanelRenderTarget& operator=(const FrontPanelRenderTarget&) = delete; + + void CreateDeviceDependentResources(_In_ IXboxFrontPanelControl *frontPanelControl, _In_ ID3D11Device *device); + + void Clear(_In_ ID3D11DeviceContext *context, const float ColorRGBA[4]); + void SetAsRenderTarget(_In_ ID3D11DeviceContext *context); + + ID3D11Texture2D *GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_renderTargetView.Get(); } + DXGI_FORMAT GetRenderTargetFormat() const { return m_renderTargetFormat; } + + // Render a grayscale image using the provided shader resource view as the source + void GPUBlit(_In_ ID3D11DeviceContext *context, _In_ ID3D11ShaderResourceView *srcSRV); + + // Copy the render target to a staging texture and then copy it back to the CPU + void CopyToBuffer(_In_ ID3D11DeviceContext *context, BufferDesc &desc); + + // Copy the render target to a staging texture, copy the result back to the CPU + // and then present it to the front panel display + void PresentToFrontPanel(_In_ ID3D11DeviceContext *context); + + protected: + // Front Panel object + Microsoft::WRL::ComPtr m_frontPanelControl; + uint32_t m_displayWidth; + uint32_t m_displayHeight; + + // Render Target and Depth Buffer + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_renderTargetView; + DXGI_FORMAT m_renderTargetFormat; + + // Resources for GPU Blit / Present + std::unique_ptr m_panelBlt; + std::unique_ptr m_buffer; + Microsoft::WRL::ComPtr m_staging; + }; +} diff --git a/Kits/ATGTK/FrontPanel/RasterFont.cpp b/Kits/ATGTK/FrontPanel/RasterFont.cpp new file mode 100644 index 0000000000000000000000000000000000000000..12a1639ad6ec8ed16b5cd6b24bf8c787e0260ae9 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/RasterFont.cpp @@ -0,0 +1,486 @@ +//-------------------------------------------------------------------------------------- +// RasterFont.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "RasterFont.h" +#include "FileHelpers.h" +#include "OSHelpers.h" +#include "Serialization.h" +#include "BufferDescriptor.h" + +#include +#include +#include +#include + +using namespace ATG; + +//-------------------------------------------------------------------------------------- +// RasterGlyphSheet implementation +//-------------------------------------------------------------------------------------- +#pragma region RasterGlyphSheet + +namespace ATG +{ + static inline bool operator<(const RasterGlyphSheet::RasterGlyph &left, const RasterGlyphSheet::RasterGlyph &right) + { + return left.character < right.character; + } + + static inline bool operator< (wchar_t left, const RasterGlyphSheet::RasterGlyph &right) + { + return left < right.character; + } + + static inline bool operator< (const RasterGlyphSheet::RasterGlyph &left, wchar_t right) + { + return left.character < right; + } + + static inline bool operator<(const RasterGlyphSheet::KerningPair &leftPair, const RasterGlyphSheet::KerningPair &rightPair) + { + return (leftPair.first < rightPair.first) || ((leftPair.first == rightPair.first) && (leftPair.second < rightPair.second)); + } +} + +RasterGlyphSheet::RasterGlyphSheet( + uint16_t effectiveAscent, + uint16_t effectiveDescent, + const std::vector &glyphs, + const std::vector &kerns, + uint32_t glyphPixelBytes, + const uint8_t *glyphPixels, + wchar_t defaultGlyph) + : m_effectiveAscent(effectiveAscent) + , m_effectiveDescent(effectiveDescent) + , m_glyphs(glyphs) + , m_kerns(kerns) + , m_glyphPixelBytes(glyphPixelBytes) + , m_defaultGlyph(nullptr) +{ + // Sort the glyphs + std::sort(m_glyphs.begin(), m_glyphs.end()); + + // Sort the kerning pairs + std::sort(m_kerns.begin(), m_kerns.end()); + + //assert(false); // NEED TO SORT THE GLYPHS AND KERNING PAIRS! + m_glyphPixels.reset(new uint8_t[glyphPixelBytes]); + memcpy_s(m_glyphPixels.get(), glyphPixelBytes, glyphPixels, glyphPixelBytes); + SetDefaultGlyph(defaultGlyph); +} + +RasterGlyphSheet::~RasterGlyphSheet() +{ +} + +void RasterGlyphSheet::SetDefaultGlyph(wchar_t character) +{ + m_defaultGlyph = FindGlyph(character); +} + +const RasterGlyphSheet::RasterGlyph *RasterGlyphSheet::FindGlyph(wchar_t character) const +{ + auto glyph = std::lower_bound(m_glyphs.begin(), m_glyphs.end(), character); + + if (glyph != m_glyphs.end() && glyph->character == character) + { + return &*glyph; + } + + return m_defaultGlyph; +} + +const RasterGlyphSheet::KerningPair * RasterGlyphSheet::FindKerningPair(wchar_t first, wchar_t second) const +{ + KerningPair testPair = {}; + testPair.amount = 0; + testPair.first = first; + testPair.second = second; + + auto kPair = std::lower_bound(m_kerns.begin(), m_kerns.end(), testPair); + + if (kPair != m_kerns.end() && kPair->first == first && kPair->second == second) + { + return &*kPair; + } + + return nullptr; +} + +#pragma endregion + +//-------------------------------------------------------------------------------------- +// RasterFont implementation +//-------------------------------------------------------------------------------------- +#pragma region RasterFont + +RasterFont::RasterFont() +{ +} + +RasterFont::RasterFont(const wchar_t *filename) + : m_glyphs(new RasterGlyphSheet) +{ + wchar_t inFile[MAX_PATH] = L""; + { + wcscpy_s(inFile, filename); + + // Add a file extension if it doesn't already have one + wchar_t *dot = wcsrchr(inFile, '.'); + if (!dot) + { + wcscat_s(inFile, L".rasterfont"); + } + } + + std::ifstream stream(inFile, std::ios::in | std::ios::binary); + if (stream.bad() || stream.fail()) + { + uint32_t err = GetLastError(); + char buffer[128]; + sprintf_s(buffer, "Unable to open file %ls. Error code: 0x%08X", inFile, err); + throw std::exception(buffer); + } + + StreamDeserializationBuffer sdb(stream); + SerializationHeader header; + + try + { + Deserialize(header, sdb); + } + catch (std::bad_alloc &) + { + char buffer[128]; + sprintf_s(buffer, "File (%ls) does not contain a valid serialization header", inFile); + throw std::exception(buffer); + } + + using SHFlags = SerializationHeader::SerializationFlags; + + if (!header.CheckFlag(SHFlags::is_current_version)) + { + char buffer[128]; + sprintf_s(buffer, "File (%ls) was serialized with an incompatible version", inFile); + throw std::exception(buffer); + } + + if (!header.CheckFlag(SHFlags::is_host_endian)) + { + char buffer[128]; + sprintf_s(buffer, "File (%ls) was serialized with an incompatible byte-order", inFile); + throw std::exception(buffer); + } + + RasterFontHeader rfHeader; + try + { + Deserialize(rfHeader, sdb); + } + catch (std::bad_alloc &) + { + char buffer[128]; + sprintf_s(buffer, "File (%ls) is not a valid Raster Font file", inFile); + throw std::exception(buffer); + } + + if (!rfHeader.IsValidHeaderName()) + { + char buffer[128]; + sprintf_s(buffer, "File (%ls) is not a valid Raster Font file", inFile); + throw std::exception(buffer); + } + + if (!rfHeader.IsCompatibleVersion()) + { + char buffer[128]; + sprintf_s(buffer, "File (%ls) is not a compatible Raster Font version", inFile); + throw std::exception(buffer); + } + + Deserialize(*m_glyphs.get(), sdb); +} + +RasterFont::RasterFont(std::unique_ptr&& glyphs) + : m_glyphs(std::move(glyphs)) +{ +} + +RasterFont::RasterFont(RasterFont && other) +{ + m_glyphs = std::move(other.m_glyphs); +} + +RasterFont & RasterFont::operator=(RasterFont && other) +{ + RasterFont temp(std::move(other)); + m_glyphs = std::move(temp.m_glyphs); + return *this; +} + +RasterFont::~RasterFont() +{} + +void RasterFont::WriteToFile(const wchar_t * filename) const +{ + wchar_t outFile[MAX_PATH] = L""; + { + wcscpy_s(outFile, filename); + + // Add a file extension if it doesn't already have one + wchar_t *dot = wcsrchr(outFile, '.'); + if (!dot) + { + wcscat_s(outFile, L".rasterfont"); + } + } + + // Note: using a std::ofstream below, however we sitll use CreateFile2 to get a handle in order + // to support the auto_delete_file functionality + ScopedHandle hFile(safe_handle(CreateFile2(outFile, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr))); + + if (!hFile) + { + char buffer[128]; + uint32_t err = GetLastError(); + sprintf_s(buffer, "Unable to create file %ls. Error code: 0x%08X\n", outFile, err); + throw std::exception(buffer); + } + + auto_delete_file delonFail(hFile.get()); + + // Serialize the glyph sheet to a filestream + { + // Some gymnastics to get the file handle into the ofstream + int fileDesc = _open_osfhandle((intptr_t)hFile.get(), 0); + if (fileDesc == -1) + { + char buffer[128]; + uint32_t err = GetLastError(); + sprintf_s(buffer, "Unable to get file descriptor %ls. Error code: 0x%08X\n", outFile, err); + throw std::exception(buffer); + } + + FILE *file = _fdopen(fileDesc, "w"); + if (file != nullptr) + { + std::ofstream stream(file); + hFile.reset(); + + StreamSerializationBuffer ssb(stream); + SerializationHeader header; + Serialize(header, ssb); + + RasterFontHeader rfHeader; + Serialize(rfHeader, ssb); + + Serialize(*m_glyphs.get(), ssb); + + // This will close the stream, fileDesc and the file handle + stream.close(); + } + } + + delonFail.clear(); +} + +const RasterGlyphSheet & RasterFont::GetGlyphs() const +{ + return *m_glyphs.get(); +} + +unsigned RasterFont::GetLineSpacing() const +{ + return m_glyphs->GetEffectiveAscent() + m_glyphs->GetEffectiveDescent(); +} + +RECT RasterFont::MeasureString(const wchar_t *text) const +{ + auto& glyphSheet = *m_glyphs.get(); + RECT r = {}; + + if (!&glyphSheet) + { + assert(&glyphSheet && "Not initialized"); + return r; + } + + unsigned lineSpacing = GetLineSpacing(); + + glyphSheet.ForEachGlyph(text, lineSpacing, [&](const RasterGlyphSheet::RasterGlyph &glyph, unsigned cellOriginX, unsigned cellOriginY) { + RECT bbRect = {}; + + bbRect.left = cellOriginX + glyph.blackBoxOriginX; + bbRect.right = bbRect.left + glyph.blackBoxWidth; + + bbRect.top = cellOriginY - glyph.blackBoxOriginY; + bbRect.bottom = bbRect.top + glyph.blackBoxHeight; + + r.top = std::min(r.top, bbRect.top); + r.bottom = std::max(r.bottom, bbRect.bottom); + + r.left = std::min(r.left, bbRect.left); + r.right = std::max(r.right, bbRect.right); + }); + + return r; +} + +RECT RasterFont::MeasureStringFmt(const wchar_t *format, ...) const +{ + std::unique_ptr buffer; + { + va_list args; + va_start(args, format); + + auto count = _vscwprintf(format, args); + buffer = std::make_unique(count + 1); + buffer.get()[count] = L'\0'; + + vswprintf_s(buffer.get(), count + 1, format, args); + + va_end(args); + } + + return MeasureString(buffer.get()); +} + +void RasterFont::DrawString(const BufferDesc &destBuffer, unsigned x, unsigned y, const wchar_t *text) const +{ + DrawString(destBuffer, x, y, 0xFF, text); +} + +void RasterFont::DrawStringFmt(const BufferDesc & destBuffer, unsigned x, unsigned y, const wchar_t *format, ...) const +{ + std::unique_ptr buffer; + { + va_list args; + va_start(args, format); + + auto count = _vscwprintf(format, args); + buffer = std::make_unique(count + 1); + buffer.get()[count] = L'\0'; + + vswprintf_s(buffer.get(), count + 1, format, args); + + va_end(args); + } + + return DrawString(destBuffer, x, y, buffer.get()); +} + +void RasterFont::DrawString(const BufferDesc & destBuffer, unsigned x, unsigned y, uint8_t shade, const wchar_t * text) const +{ + unsigned lineSpacing = GetLineSpacing(); + auto& glyphSheet = *m_glyphs.get(); + if (!&glyphSheet) + { + assert(&glyphSheet && "Not initialized"); + return; + } + + RECT r = MeasureString(text); + int baseline = -r.top; + + unsigned w = r.right - r.left + x; + unsigned h = baseline + r.bottom + y; + + r.top = 0; r.bottom = w; + r.left = 0; r.right = h; + + glyphSheet.ForEachGlyph(text, lineSpacing, [&](const RasterGlyphSheet::RasterGlyph &glyph, unsigned cellOriginX, unsigned cellOriginY) { + RECT bbRect = {}; + bbRect.left = x + cellOriginX + glyph.blackBoxOriginX; + bbRect.right = bbRect.left + glyph.blackBoxWidth; + bbRect.top = y + baseline + cellOriginY - glyph.blackBoxOriginY; + bbRect.bottom = bbRect.top + glyph.blackBoxHeight; + + glyphSheet.ForEachGlyphPixel(glyph, bbRect.left, bbRect.top, [&](unsigned col, unsigned row, uint8_t clr) { + uint8_t pxl = !!clr * shade; + if (clr) + SetPixel(destBuffer, col, row, pxl); + }); + }); +} + +void RasterFont::DrawStringFmt(const BufferDesc & destBuffer, unsigned x, unsigned y, uint8_t shade, const wchar_t * format, ...) const +{ + std::unique_ptr buffer; + { + va_list args; + va_start(args, format); + + auto count = _vscwprintf(format, args); + buffer = std::make_unique(count + 1); + buffer.get()[count] = L'\0'; + + vswprintf_s(buffer.get(), count + 1, format, args); + + va_end(args); + } + + return DrawString(destBuffer, x, y, shade, buffer.get()); +} + +RECT RasterFont::MeasureGlyph(wchar_t wch) const +{ + auto& glyphSheet = *m_glyphs.get(); + RECT r = {}; + + if (!&glyphSheet) + { + assert(&glyphSheet && "Not initialized"); + return r; + } + + auto& glyph = *glyphSheet.FindGlyph(wch); + r.right = glyph.blackBoxWidth; + r.bottom = glyph.blackBoxHeight; + + return r; +} + +void RasterFont::DrawGlyph(const BufferDesc & destBuffer, unsigned x, unsigned y, wchar_t wch, uint8_t shade) const +{ + auto& glyphSheet = *m_glyphs.get(); + + if (!&glyphSheet) + { + assert(&glyphSheet && "Not initialized"); + } + + auto& glyph = *glyphSheet.FindGlyph(wch); + + + glyphSheet.ForEachGlyphPixel(glyph, x, y, [&](unsigned col, unsigned row, uint8_t clr) + { + uint8_t pxl = !!clr * shade; + if (clr) + SetPixel(destBuffer, col, row, pxl); + }); + +} +#pragma endregion + +//-------------------------------------------------------------------------------------- +// RasterFontHeader implementation +//-------------------------------------------------------------------------------------- +#pragma region RasterFontHeader + +#define RASTER_FONT_HEADER_NAME "Raster Font" +RasterFontHeader::RasterFontHeader() + : m_headerName(RASTER_FONT_HEADER_NAME) + , m_majorVersion(0) + , m_minorVersion(0) +{} + +bool RasterFontHeader::IsValidHeaderName() const +{ + return (m_headerName == RASTER_FONT_HEADER_NAME); +} + +#pragma endregion diff --git a/Kits/ATGTK/FrontPanel/RasterFont.h b/Kits/ATGTK/FrontPanel/RasterFont.h new file mode 100644 index 0000000000000000000000000000000000000000..3e635fd02a50db87b3c2521864acd480e9d70549 --- /dev/null +++ b/Kits/ATGTK/FrontPanel/RasterFont.h @@ -0,0 +1,321 @@ +//-------------------------------------------------------------------------------------- +// RasterFont.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#include +#include +#include +#include + +#include "BufferDescriptor.h" +#include "Serialization.h" + +namespace ATG +{ + template + inline unsigned GetStorageSize(unsigned bitCount) + { + static const size_t unitSize = sizeof(STORAGE_UNIT_T) * 8; + return unsigned(bitCount / unitSize + !!(bitCount % unitSize)); + } + + class RasterGlyphSheet + { + public: + + struct RasterGlyph + { + uint32_t character; + int16_t blackBoxOriginX; + int16_t blackBoxOriginY; + uint16_t blackBoxWidth; + uint16_t blackBoxHeight; + uint16_t cellIncX; + uint16_t cellIncY; + uint32_t pixelIndex; + + static ClassVisitorActions CreateClassVisitor() + { + ClassVisitorActions actions; + VisitMember(actions, &RasterGlyph::character); + VisitMember(actions, &RasterGlyph::blackBoxOriginX); + VisitMember(actions, &RasterGlyph::blackBoxOriginY); + VisitMember(actions, &RasterGlyph::blackBoxWidth); + VisitMember(actions, &RasterGlyph::blackBoxHeight); + VisitMember(actions, &RasterGlyph::cellIncX); + VisitMember(actions, &RasterGlyph::cellIncY); + VisitMember(actions, &RasterGlyph::pixelIndex); + return actions; + } + }; + + struct KerningPair + { + wchar_t first; + wchar_t second; + int32_t amount; + + static ClassVisitorActions CreateClassVisitor() + { + ClassVisitorActions actions; + VisitMember(actions, &KerningPair::first); + VisitMember(actions, &KerningPair::second); + VisitMember(actions, &KerningPair::amount); + return actions; + } + }; + + RasterGlyphSheet() + : m_effectiveAscent(0) + , m_effectiveDescent(0) + , m_glyphPixelBytes(0) + , m_defaultGlyph(nullptr) + { + } + + RasterGlyphSheet( + uint16_t effectiveAscent, + uint16_t effectiveDescent, + const std::vector &glyphs, + const std::vector &kerns, + uint32_t glyphPixelBytes, + const uint8_t *glyhpPixels, + wchar_t defaultGlyph); + + using GlyphIterator = std::vector::const_iterator; + + virtual ~RasterGlyphSheet(); + + int GetEffectiveAscent() const { return m_effectiveAscent; } + int GetEffectiveDescent() const { return m_effectiveDescent; } + size_t GetGlyphCount() const { return m_glyphs.size(); } + GlyphIterator begin() const { return m_glyphs.begin(); } + GlyphIterator end() const { return m_glyphs.end(); } + const RasterGlyph *GetDefaultGlyph() const { return m_defaultGlyph; } + void SetDefaultGlyph(wchar_t character); + const RasterGlyph *FindGlyph(wchar_t character) const; + const KerningPair *FindKerningPair(wchar_t first, wchar_t second) const; + + template + void ForEachGlyphPixel(const RasterGlyph &glyph, unsigned bbOriginX, unsigned bbOriginY, ACTION_T fn) const + { + const unsigned rows = glyph.blackBoxHeight; + const unsigned cols = glyph.blackBoxWidth; + const unsigned glyphByteCount = GetStorageSize(cols * rows); + + uint8_t *srcByte = &m_glyphPixels.get()[glyph.pixelIndex]; + unsigned col = 0; + unsigned row = 0; + for (unsigned i = 0; i < glyphByteCount; ++i) + { + for (int shift = 7; shift >= 0; --shift) + { + if (row == rows) + return; + + uint8_t clr = (((srcByte[i]) >> shift) & 0x1) * 0xFF; + fn(col + bbOriginX, row + bbOriginY, clr); + ++col; + + if (col == cols) + { + ++row; + col = 0; + } + } + } + } + + template + void ForEachGlyph(const wchar_t *text, unsigned lineSpacing, ACTION_T fn) const + { + unsigned cellOriginX = 0; + unsigned cellOriginY = 0; + + for (const wchar_t *txt = text; *txt; ++txt) + { + wchar_t character = *txt; + + switch (character) + { + case '\r': + // Skip carriage returns + continue; + + case '\n': + // New line + cellOriginX = 0; + cellOriginY += lineSpacing; + break; + + default: + // Output this character + auto glyph = FindGlyph(character); + + if (!iswspace(character) + || glyph->blackBoxWidth > 1 + || glyph->blackBoxHeight > 1) + { + fn(*glyph, cellOriginX, cellOriginY); + } + + int x = int(cellOriginX) + glyph->cellIncX; + + // do kerning + const wchar_t *next = txt + 1; + if (*next) + { + auto kpair = FindKerningPair(*txt, *next); + if (kpair) + { + x += kpair->amount; + } + + } + cellOriginX = (x < 0) ? 0 : x; + + cellOriginY += glyph->cellIncY; + } + } + } + + static ClassVisitorActions CreateClassVisitor() + { + ClassVisitorActions actions; + VisitMember(actions, &RasterGlyphSheet::m_effectiveAscent); + VisitMember(actions, &RasterGlyphSheet::m_effectiveDescent); + VisitVectorCollection(actions, &RasterGlyphSheet::m_glyphs); + VisitVectorCollection(actions, &RasterGlyphSheet::m_kerns); + VisitUniquePointerCollection(actions, &RasterGlyphSheet::m_glyphPixels, &RasterGlyphSheet::m_glyphPixelBytes); + VisitGetterSetter( + actions, + [](const RasterGlyphSheet &rgs) { + return wchar_t(rgs.m_defaultGlyph ? rgs.m_defaultGlyph->character : '\0'); + }, + [](RasterGlyphSheet &rgs, wchar_t defaultGlyph) { + rgs.SetDefaultGlyph(defaultGlyph); + }); + return actions; + } + + private: + uint16_t m_effectiveAscent; + uint16_t m_effectiveDescent; + std::vector m_glyphs; + std::vector m_kerns; + uint32_t m_glyphPixelBytes; + std::unique_ptr m_glyphPixels; + const RasterGlyph *m_defaultGlyph; + }; + + class RasterFont + { + public: + RasterFont(); + RasterFont(const wchar_t *filename); + RasterFont(std::unique_ptr &&glyphs); + + RasterFont(RasterFont &&other); + RasterFont(const RasterFont &) = delete; + RasterFont &operator=(RasterFont &&other); + RasterFont &operator=(RasterFont&) = delete; + + ~RasterFont(); + + void WriteToFile(const wchar_t *filename) const; + + const RasterGlyphSheet &GetGlyphs() const; + + unsigned GetLineSpacing() const; + + // MeastureString and MeasureStringFMt are useful for computing text bounds for layout purposes + RECT MeasureString(const wchar_t *text) const; + RECT MeasureStringFmt(const wchar_t *format, ...) const; + + // Basic text rendering to a buffer + void DrawString(const struct BufferDesc &destBuffer, unsigned x, unsigned y, const wchar_t *text) const; + + // Formatted text rendering to a buffer + void DrawStringFmt(const struct BufferDesc &destBuffer, unsigned x, unsigned y, const wchar_t *format, ...) const; + + // The following DrawString variants provide a shade parameter that lets you specify different shades of gray + void DrawString(const struct BufferDesc &destBuffer, unsigned x, unsigned y, uint8_t shade, const wchar_t *text) const; + void DrawStringFmt(const struct BufferDesc &destBuffer, unsigned x, unsigned y, uint8_t shade, const wchar_t *format, ...) const; + + // The glyph-specific methods are used for precisely positioning a single glyph + RECT MeasureGlyph(wchar_t wch) const; + void DrawGlyph(const struct BufferDesc &destBuffer, unsigned x, unsigned y, wchar_t wch, uint8_t shade = 0xFF) const; + + private: + std::unique_ptr m_glyphs; + }; + + + + class RasterFontHeader + { + public: + static const uint16_t CURRENT_MAJOR_VERSION = 0; + static const uint16_t CURRENT_MINOR_VERSION = 1; + + RasterFontHeader(); + + uint16_t GetMajorVersion() const { return m_majorVersion; } + uint16_t GetMinorVersion() const { return m_minorVersion; } + + static ClassVisitorActions CreateClassVisitor() + { + ClassVisitorActions actions; + + // Serialize/Deserialize the header name + VisitString(actions, &RasterFontHeader::m_headerName); + + // Serialize/Deserialize the major version + VisitGetterSetter( + actions, + [](const RasterFontHeader &) + { + // Deliver the current major version to the serializer + return CURRENT_MAJOR_VERSION; + }, + [](RasterFontHeader &header, uint16_t majorVer) + { + // Consume the major version from the deserialization stream and set the major version + header.m_majorVersion = majorVer; + }); + + // Serialize/Deserialize the minor version + VisitGetterSetter( + actions, + [](const RasterFontHeader &) + { + // Deliver the current minor version to the serializer + return CURRENT_MINOR_VERSION; + }, + [](RasterFontHeader &header, uint16_t minorVer) + { + // Consume the minor version from the deserialization stream and set the minor version + header.m_minorVersion = minorVer; + }); + + return actions; + } + + bool IsValidHeaderName() const; + + bool IsCompatibleVersion() const + { + // Currently only accepting a strict match for both version numbers + return (m_majorVersion == CURRENT_MAJOR_VERSION) && (m_minorVersion == CURRENT_MINOR_VERSION); + } + + private: + std::string m_headerName; + uint16_t m_majorVersion; + uint16_t m_minorVersion; + }; + +} // namespace ATG diff --git a/Kits/ATGTK/FullScreenQuad/FullScreenQuad.cpp b/Kits/ATGTK/FullScreenQuad/FullScreenQuad.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52f5308c4fe825e8298e58f1cc157963857b55a4 --- /dev/null +++ b/Kits/ATGTK/FullScreenQuad/FullScreenQuad.cpp @@ -0,0 +1,157 @@ +//-------------------------------------------------------------------------------------- +// FullScreenQuad.cpp +// +// Class to draw a full-screen quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FullScreenQuad.h" + +#include "DirectXHelpers.h" + +using Microsoft::WRL::ComPtr; +using namespace DX; + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) +//====================================================================================== +// Direct3D 12 +//====================================================================================== + +// Root signature layout +enum RootParameterIndex +{ + ConstantBuffer, + TextureSRV, + Count +}; + +// Initialize +void FullScreenQuad::Initialize(_In_ ID3D12Device* d3dDevice) +{ + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_DESCRIPTOR_RANGE textureSRVs(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + + CD3DX12_STATIC_SAMPLER_DESC sampler( + 0, // register + D3D12_FILTER_MIN_MAG_MIP_POINT, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + 0.0f, + 16, + D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + 0.0f, + D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY_PIXEL); + + CD3DX12_ROOT_PARAMETER rootParameters[static_cast(RootParameterIndex::Count)]; + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_PIXEL); + rootParameters[RootParameterIndex::TextureSRV].InitAsDescriptorTable(1, &textureSRVs, D3D12_SHADER_VISIBILITY_PIXEL); + + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; + rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, rootSignatureFlags); + + ComPtr signature; + ComPtr error; + DX::ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + DX::ThrowIfFailed(d3dDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(m_d3dRootSignature.ReleaseAndGetAddressOf()))); +} + +// Draw the full screen quad +_Use_decl_annotations_ +void FullScreenQuad::Draw( + ID3D12GraphicsCommandList* d3dCommandList, + ID3D12PipelineState* d3dPSO, + D3D12_GPU_DESCRIPTOR_HANDLE texture, + D3D12_GPU_VIRTUAL_ADDRESS constantBuffer) +{ + d3dCommandList->SetGraphicsRootSignature(m_d3dRootSignature.Get()); + d3dCommandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, constantBuffer); + d3dCommandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRV, texture); + d3dCommandList->SetPipelineState(d3dPSO); + d3dCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + d3dCommandList->DrawInstanced(4, 1, 0, 0); +} + +void FullScreenQuad::ReleaseDevice() +{ + m_d3dRootSignature.Reset(); +} + +#else +//====================================================================================== +// Direct3D 11 +//====================================================================================== + +#include "CommonStates.h" +#include "ReadData.h" + +// Initialize +void FullScreenQuad::Initialize(_In_ ID3D11Device* d3dDevice) +{ + if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) + { + throw std::exception("FullScreenQuad requires Direct3D hardware feature level 10.0 or better"); + } + + auto vertexShaderBlob = DX::ReadData(L"FullScreenQuadVS.cso"); + DX::ThrowIfFailed( + d3dDevice->CreateVertexShader(vertexShaderBlob.data(), vertexShaderBlob.size(), nullptr, + m_vertexShader.ReleaseAndGetAddressOf())); + + auto pixelShaderBlob = DX::ReadData(L"FullScreenQuadPS.cso"); + DX::ThrowIfFailed( + d3dDevice->CreatePixelShader(pixelShaderBlob.data(), pixelShaderBlob.size(), nullptr, + m_pixelShader.ReleaseAndGetAddressOf())); +} + +_Use_decl_annotations_ +void FullScreenQuad::Draw( + ID3D11DeviceContext* d3dContext, + DirectX::CommonStates& states, + ID3D11ShaderResourceView* texture, + std::function setCustomState) +{ + // Set the texture. + ID3D11ShaderResourceView* textures[1] = { texture }; + d3dContext->PSSetShaderResources(0, 1, textures); + + auto sampler = states.LinearClamp(); + d3dContext->PSSetSamplers(0, 1, &sampler); + + // Set state objects. + d3dContext->OMSetBlendState(states.Opaque(), nullptr, 0xffffffff); + d3dContext->OMSetDepthStencilState(states.DepthNone(), 0); + d3dContext->RSSetState(states.CullNone()); + + // Set shaders. + d3dContext->VSSetShader(m_vertexShader.Get(), nullptr, 0); + d3dContext->PSSetShader(m_pixelShader.Get(), nullptr, 0); + + if (setCustomState) + { + setCustomState(); + } + + // Draw quad. + d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + d3dContext->Draw(4, 0); +} + +void FullScreenQuad::ReleaseDevice() +{ + m_vertexShader.Reset(); + m_pixelShader.Reset(); +} + +#endif \ No newline at end of file diff --git a/Kits/ATGTK/FullScreenQuad/FullScreenQuad.h b/Kits/ATGTK/FullScreenQuad/FullScreenQuad.h new file mode 100644 index 0000000000000000000000000000000000000000..44c236ca3f8347e19c66ee26845e37a13cba7f96 --- /dev/null +++ b/Kits/ATGTK/FullScreenQuad/FullScreenQuad.h @@ -0,0 +1,52 @@ +//-------------------------------------------------------------------------------------- +// FullScreenQuad.h +// +// Class to draw a full-screen quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include + + +namespace DX +{ + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) + + class FullScreenQuad + { + public: + void Initialize(_In_ ID3D12Device* d3dDevice); + void Draw(_In_ ID3D12GraphicsCommandList* d3dCommandList, _In_ ID3D12PipelineState* d3dPSO, D3D12_GPU_DESCRIPTOR_HANDLE texture, D3D12_GPU_VIRTUAL_ADDRESS constantBuffer = 0); + + void ReleaseDevice(); + + ID3D12RootSignature* GetRootSignature() const { return m_d3dRootSignature.Get(); } + + private: + Microsoft::WRL::ComPtr m_d3dRootSignature; + }; + +#elif defined(__d3d11_h__) || defined(__d3d11_x_h__) + + class FullScreenQuad + { + public: + void Initialize(_In_ ID3D11Device* d3dDevice); + void Draw(_In_ ID3D11DeviceContext* d3dContext, DirectX::CommonStates& states, _In_ ID3D11ShaderResourceView* texture, _In_opt_ std::function setCustomState = nullptr); + void ReleaseDevice(); + + private: + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_pixelShader; + }; + +#else +# error Please #include or +#endif + +} \ No newline at end of file diff --git a/Kits/ATGTK/FullScreenQuad/FullScreenQuad.hlsli b/Kits/ATGTK/FullScreenQuad/FullScreenQuad.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..e7fb897d4212e033465685a2395b699aac0256d9 --- /dev/null +++ b/Kits/ATGTK/FullScreenQuad/FullScreenQuad.hlsli @@ -0,0 +1,36 @@ +//-------------------------------------------------------------------------------------- +// FullScreenQuad.hlsli +// +// Common shader code to draw a full-screen quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#ifndef __FULLSCREENQUAD_HLSLI__ +#define __FULLSCREENQUAD_HLSLI__ + +#define FullScreenQuadRS \ + "RootFlags ( DENY_VERTEX_SHADER_ROOT_ACCESS |" \ + " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ + " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ + " DENY_HULL_SHADER_ROOT_ACCESS )," \ + "CBV(b0, visibility = SHADER_VISIBILITY_PIXEL ), " \ + "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ + "StaticSampler(s0,"\ + " filter = FILTER_MIN_MAG_MIP_POINT,"\ + " addressU = TEXTURE_ADDRESS_CLAMP,"\ + " addressV = TEXTURE_ADDRESS_CLAMP,"\ + " addressW = TEXTURE_ADDRESS_CLAMP,"\ + " visibility = SHADER_VISIBILITY_PIXEL )" + +SamplerState PointSampler : register(s0); +Texture2D Texture : register(t0); + +struct Interpolators +{ + float4 Position : SV_Position; + float2 TexCoord : TEXCOORD0; +}; + +#endif \ No newline at end of file diff --git a/Kits/ATGTK/FullScreenQuad/FullScreenQuadPS.hlsl b/Kits/ATGTK/FullScreenQuad/FullScreenQuadPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..63b371cba7b660f8534cf97b77c753202bde3aa3 --- /dev/null +++ b/Kits/ATGTK/FullScreenQuad/FullScreenQuadPS.hlsl @@ -0,0 +1,21 @@ +//-------------------------------------------------------------------------------------- +// FullScreenQuadPS.hlsl +// +// A simple pixel shader to render a texture +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "FullScreenQuad.hlsli" + +float4 main11(Interpolators In) : SV_Target0 +{ + return Texture.Sample(PointSampler, In.TexCoord); +} + +[RootSignature(FullScreenQuadRS)] +float4 main(Interpolators In) : SV_Target0 +{ + return main11(In); +} \ No newline at end of file diff --git a/Kits/ATGTK/FullScreenQuad/FullScreenQuadVS.hlsl b/Kits/ATGTK/FullScreenQuad/FullScreenQuadVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..d15bc9fd7cda3fa1a08e5ac431d5b6420b856394 --- /dev/null +++ b/Kits/ATGTK/FullScreenQuad/FullScreenQuadVS.hlsl @@ -0,0 +1,27 @@ +//-------------------------------------------------------------------------------------- +// FullScreenQuadVS.hlsl +// +// Simple vertex shader to draw a full-screen quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "FullScreenQuad.hlsli" + +Interpolators main11(uint vI : SV_VertexId) +{ + Interpolators output; + + float2 texcoord = float2(vI & 1, vI >> 1); + output.TexCoord = texcoord; + output.Position = float4((texcoord.x - 0.5f) * 2.0f, -(texcoord.y - 0.5f) * 2.0f, 0.0f, 1.0f); + + return output; +} + +[RootSignature(FullScreenQuadRS)] +Interpolators main(uint vI : SV_VertexId) +{ + return main11(vI); +} \ No newline at end of file diff --git a/Kits/ATGTK/HDR/HDRCommon.h b/Kits/ATGTK/HDR/HDRCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..dd452042f8844a04e5bbc2a04ed7d3c98eb3cf7f --- /dev/null +++ b/Kits/ATGTK/HDR/HDRCommon.h @@ -0,0 +1,90 @@ +//-------------------------------------------------------------------------------------- +// HDRCommon.h +// +// Simple helper functions for HDR +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +namespace DX +{ + // The ST.2084 spec defines max nits as 10,000 nits + const float g_MaxNitsFor2084 = 10000.0f; + + // Apply the ST.2084 curve to normalized linear values and outputs normalized non-linear values + float LinearToST2084(float normalizedLinearValue) + { + float ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), 0.1593017578f)) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), 0.1593017578f)), 78.84375f); + return ST2084; // Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits + } + + // ST.2084 to linear, resulting in a linear normalized value + float ST2084ToLinear(float ST2084) + { + float normalizedLinear = pow(__max(pow(abs(ST2084), 1.0f / 78.84375f) - 0.8359375f, 0.0f) / (18.8515625f - 18.6875f * pow(abs(ST2084), 1.0f / 78.84375f)), 1.0f / 0.1593017578f); + return normalizedLinear; + } + + // Takes as inout the non-normalized value from the HDR scene. This function is only used to output UI values + float LinearToST2084(float hdrSceneValue, float paperWhiteNits) + { + // HDR scene will have values zero to larger than 1, e.g. [0..100], but the ST.2084 curve + // transforms a normalized linear value, so we first need to normalize the HDR scene value. + // To do this, we need define at what brightness/nits paper white is, i.e. how bright is + // the value of 1.0f in the HDR scene. + float normalizedLinearValue = hdrSceneValue * paperWhiteNits / g_MaxNitsFor2084; + + return LinearToST2084(normalizedLinearValue); + } + + // Calculates the normalized linear value going into the ST.2084 curve, using the nits + float CalcNormalizedLinearValue(float nits) + { + return nits / g_MaxNitsFor2084; // Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits + } + + // Calc normalized linear value from hdrScene and paper white nits + float CalcNormalizedLinearValue(float hdrSceneValue, float paperWhiteNits) + { + float normalizedLinearValue = hdrSceneValue * paperWhiteNits / g_MaxNitsFor2084; + return normalizedLinearValue; // Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits + } + + // Calculates the brightness in nits for a certain normalized linear value + float CalcNits(float normalizedLinearValue) + { + return normalizedLinearValue * g_MaxNitsFor2084; + } + + // Calculates the brightness in nits for a certain linear value in the HDR scene + float CalcNits(float hdrSceneValue, float paperWhiteNits) + { + float normalizedLinear = CalcNormalizedLinearValue(hdrSceneValue, paperWhiteNits); + return CalcNits(normalizedLinear); + } + + // Calc the value that the HDR scene has to use to output a certain brightness + float CalcHDRSceneValue(float nits, float paperWhiteNits) + { + return nits / paperWhiteNits; + } + + // Calc HDR scene value from normalized value and paper white nits + float CalcHDRSceneValueFromNormalizedValue(float normalizedLinearValue, float paperWhiteNits) + { + float hdrSceneValue = normalizedLinearValue * g_MaxNitsFor2084 / paperWhiteNits; + return hdrSceneValue; + } +} \ No newline at end of file diff --git a/Kits/ATGTK/HDR/HDRCommon.hlsli b/Kits/ATGTK/HDR/HDRCommon.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..2beb0e2b05072f159b254860b5b97427dee7fd51 --- /dev/null +++ b/Kits/ATGTK/HDR/HDRCommon.hlsli @@ -0,0 +1,163 @@ +//-------------------------------------------------------------------------------------- +// HDRCommon.hlsli +// +// Shader code helper functions for HDR, such as color rotation, ST.2084, etc. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#ifndef __HDRCOMMON_HLSLI__ +#define __HDRCOMMON_HLSLI__ + +// The ST.2084 spec defines max nits as 10,000 nits +static const float g_MaxNitsFor2084 = 10000.0f; + +// Color rotation matrix to rotate Rec.709 color primaries into Rec.2020 +static const float3x3 from709to2020 = +{ + { 0.6274040f, 0.3292820f, 0.0433136f }, + { 0.0690970f, 0.9195400f, 0.0113612f }, + { 0.0163916f, 0.0880132f, 0.8955950f } +}; + +// Color rotation matrix to rotate DCI-P3 color primaries into Rec.2020 +static const float3x3 fromP3to2020 = +{ + { 0.753845, 0.198593, 0.047562 }, + { 0.0457456, 0.941777, 0.0124772 }, + { -0.00121055, 0.0176041, 0.983607 } +}; + +// Rotation matrix describing a custom color space which is bigger than Rec.709, but a little smaller than P3 +// This enhances colors, especially in the SDR range, by being a little more saturated. This can be used instead +// of from709to2020. +static const float3x3 fromExpanded709to2020 = +{ + { 0.6274040f, 0.3292820f, 0.0433136f }, + { 0.0457456, 0.941777, 0.0124772 }, + { -0.00121055, 0.0176041, 0.983607 } +}; + + +//-------------------------------------------------------------------------------------------------------------------- +// Name: LinearToST2084 +// Desc: Calculates the normalized non-linear ST.2084 value given a normalized linear value +// In: normalizedLinearValue - Linear HDR scene value normalized using paper white nits, see NormalizeHDRSceneValue() +// Out: Normalized non-linear ST.2084 value +//-------------------------------------------------------------------------------------------------------------------- + +float3 LinearToST2084(float3 normalizedLinearValue) +{ + float3 ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), 0.1593017578f)) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), 0.1593017578f)), 78.84375f); + return ST2084; // Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits +} + + +//-------------------------------------------------------------------------------------------------------------------- +// Name: ST2084ToLinear +// Desc: Calculates the normalized linear value given a normalized non-linear ST.2084 value +// In: normalizedLinearValue - Linear HDR scene value normalized using paper white nits, see NormalizeHDRSceneValue() +// Out: Normalized non-linear ST.2084 value +//-------------------------------------------------------------------------------------------------------------------- + +float3 ST2084ToLinear(float3 ST2084) +{ + float3 normalizedLinear = pow(max(pow(abs(ST2084), 1.0f / 78.84375f) - 0.8359375f, 0.0f) / (18.8515625f - 18.6875f * pow(abs(ST2084), 1.0f / 78.84375f)), 1.0f / 0.1593017578f); + return normalizedLinear; +} + + +//-------------------------------------------------------------------------------------------------------------------- +// Name: NormalizeHDRSceneValue +// Desc: Per spec, the max nits for ST.2084 is 10,000 nits. We need to establish what the value of 1.0f means +// by normalizing the values using the defined nits for paper white. According to SDR specs, paper white +// is 80 nits, but that is paper white in a cinema with a dark envirnment, and is perceived as grey on +// a display in office and living room environments. This value should be tuned according to the nits +// that the consumer perceives as white in his living room, e.g. 200 nits. As refernce, PC monitors is +// normally in the range 200-300 nits, SDR TVs 150-250 nits +// In: hdrSceneValue - Linear HDR scene value normalized using paper white nits +// paperWhiteNits - Defines how bright white is, which controls how bright the SDR range is, e.g. 200 nits +// Out: A normalized linear value that can be used as input to the ST.2084 curve +//-------------------------------------------------------------------------------------------------------------------- + +float3 NormalizeHDRSceneValue(float3 hdrSceneValue, float paperWhiteNits) +{ + float3 normalizedLinearValue = hdrSceneValue * paperWhiteNits / g_MaxNitsFor2084; + return normalizedLinearValue; // Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits +} + + +//-------------------------------------------------------------------------------------------------------------------- +// Name: CalcHDRSceneValue +// Desc: Calc the value that the HDR scene has to use to output a certain brightness +// In: nits - The brightness in nits +// paperWhiteNits - Defines how bright white is, which controls how bright the SDR range is, e.g. 200 nits +// Out: The linear HDR scene value that represents the brightness in nits +//-------------------------------------------------------------------------------------------------------------------- + +float CalcHDRSceneValue(float nits, float paperWhiteNits) +{ + return nits / paperWhiteNits; +} + + +//-------------------------------------------------------------------------------------------------------------------- +// Name: CalcHDRSceneValue +// Desc: Maps HDR values to the max brightness of the TV, so that we don't clip details that are brighter than what the +// TV can display. This can be used instead of LinearToST2084(). Refer to the HDRDisplayMapping and HDRCalibrations +// samples, and the "HDR Display Mapping" white paper +// In: normalizedLinearValue - Linear HDR scene value normalized using paper white nits +// softShoulderStart2084 - Threshold at beginning of soft shoulder for HDR display mapping, normalized non-linear ST.2084 value +// maxBrightnessOfTV2084 - Max perceived brightness of TV, nits converted to normalized non-linear ST.2084 value +// maxBrightnessOfHDRScene2084 - Max perceived brightness of HDR scene, nits converted to normalized non-linear ST.2084 value +// Out: Normalized non-linear ST.2084 value that is guarantee not to exceed the TV's max brightness +//-------------------------------------------------------------------------------------------------------------------- + +float3 MapHDRSceneToDisplayCapabilities(float3 normalizedLinearValue, float softShoulderStart2084, float maxBrightnessOfTV2084, float maxBrightnessOfHDRScene2084) +{ + float3 ST2084 = LinearToST2084(normalizedLinearValue); + + // Use a simple Bezier curve to create a soft shoulder + const float p0 = softShoulderStart2084; // First point is: soft shoulder start nits + const float p1 = maxBrightnessOfTV2084; // Middle point is: TV max nits + const float p2 = maxBrightnessOfTV2084; // Last point is also TV max nits, since values higher than TV max nits are essentially clipped to TV max brightness + const float max = maxBrightnessOfHDRScene2084; // To determine range, use max brightness of HDR scene + + float3 t = saturate((ST2084 - p0) / (max - p0)); // Amount to lerp wrt current value + float3 b0 = (p0 * (1 - t)) + (p1 * t); // Lerp between p0 and p1 + float3 b1 = (p1 * (1 - t)) + (p2 * t); // Lerp between p1 and p2 + float3 mappedValue = (b0 * (1 - t)) + (b1 * t); // Final lerp for Bezier + + mappedValue = min(mappedValue, ST2084); // If HDR scene max luminance is too close to shoulders, then it could end up producing a higher value than the ST.2084 curve, + // which will saturate colors, i.e. the opposite of what HDR display mapping should do, therefore always take minimum of the two + return (ST2084 > softShoulderStart2084) ? mappedValue : ST2084; +} + + +//-------------------------------------------------------------------------------------------------------------------- +// Name: ConvertToHDR10 +// Desc: Convert linear HDR values to HDR10 +// In: hdrSceneValue - The linear HDR scene values +// paperWhiteNits - Defines how bright white is, which controls how bright the SDR range is, e.g. 200 nits +// Out: The converted HDR10 values +//-------------------------------------------------------------------------------------------------------------------- + +float4 ConvertToHDR10(float4 hdrSceneValue, float paperWhiteNits) +{ + float3 rec2020 = mul(from709to2020, hdrSceneValue.rgb); // Rotate Rec.709 color primaries into Rec.2020 color primaries + float3 normalizedLinearValue = NormalizeHDRSceneValue(rec2020, paperWhiteNits); // Normalize using paper white nits to prepare for ST.2084 + float3 HDR10 = LinearToST2084(normalizedLinearValue); // Apply ST.2084 curve + + return float4(HDR10.rgb, hdrSceneValue.a); +} + + +#endif + + diff --git a/Kits/ATGTK/OSHelpers.h b/Kits/ATGTK/OSHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..3364d5f6c65bc46a56aa3c0305f947b869261029 --- /dev/null +++ b/Kits/ATGTK/OSHelpers.h @@ -0,0 +1,17 @@ +//-------------------------------------------------------------------------------------- +// OSWrappers.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +// It's required to include the proper OS header based on target platform before including this header + +// Provides wrappers around various Windows objects to make them act as RAII +namespace ATG +{ + struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } }; + typedef std::unique_ptr ScopedHandle; + inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } +} diff --git a/Kits/ATGTK/Serialization.h b/Kits/ATGTK/Serialization.h new file mode 100644 index 0000000000000000000000000000000000000000..8c904e38f5d7d09c0a5d97d0e6c5bf80180156e9 --- /dev/null +++ b/Kits/ATGTK/Serialization.h @@ -0,0 +1,1661 @@ +//-------------------------------------------------------------------------------------- +// Serialization.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include +#include +#include +#include +#include + +#define ENABLE_IF_INTEGRAL(_T_) typename std::enable_if::value>::type* = nullptr +#define ENABLE_IF_NOT_INTEGRAL(_T_) typename std::enable_if::value>::type* = nullptr + + +//-------------------------------------------------------------------------------------- +// Interfaces for a generic Visitor implementation +//-------------------------------------------------------------------------------------- +#pragma region Visitor +namespace ATG +{ + class IConstVisitor + { + public: + virtual ~IConstVisitor() {} + + virtual void VisitPrimitiveElement(int8_t elt) = 0; + virtual void VisitPrimitiveElement(uint8_t elt) = 0; + virtual void VisitPrimitiveElement(int16_t elt) = 0; + virtual void VisitPrimitiveElement(uint16_t elt) = 0; + virtual void VisitPrimitiveElement(int32_t elt) = 0; + virtual void VisitPrimitiveElement(uint32_t elt) = 0; + virtual void VisitPrimitiveElement(int64_t elt) = 0; + virtual void VisitPrimitiveElement(uint64_t elt) = 0; + virtual void VisitPrimitiveElement(wchar_t elt) = 0; + virtual void VisitPrimitiveElement(char elt) = 0; + + + virtual void VisitPrimitiveCollection(const int8_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const uint8_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const int16_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const uint16_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const int32_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const uint32_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const int64_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const uint64_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const wchar_t *elts, size_t count) = 0; + virtual void VisitPrimitiveCollection(const char *elts, size_t count) = 0; + + virtual void VisitElement(class ConstVisitorContext &) = 0; + virtual void VisitCollection(size_t count, class ConstVisitorContext &) = 0; + }; + + template + class ImplementIConstVisitor : public IConstVisitor + { + public: + + void VisitPrimitiveElement(int8_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint8_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(int16_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint16_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(int32_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint32_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(int64_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint64_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(wchar_t elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(char elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + + void VisitPrimitiveCollection(const int8_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const uint8_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const int16_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const uint16_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const int32_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const uint32_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const int64_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const uint64_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const wchar_t *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + void VisitPrimitiveCollection(const char *elts, size_t count) override { static_cast(this)->ImplementVisitPrimitiveCollection(elts, count); } + + void VisitElement(class ConstVisitorContext &ctx) override + { + static_cast(this)->ImplementVisitElement(ctx); + } + + void VisitCollection(size_t count, class ConstVisitorContext &ctx) override + { + static_cast(this)->ImplementVisitCollection(count, ctx); + } + + }; + +#define DECLARE_GET_BUFFER_INTERFACE(ELT_TYPE) \ + class IGetBuffer_ ## ELT_TYPE \ + { \ + public: \ + virtual ~IGetBuffer_ ## ELT_TYPE() {} \ + virtual ELT_TYPE *GetBuffer(size_t count) = 0; \ + }; + + DECLARE_GET_BUFFER_INTERFACE(int8_t) + DECLARE_GET_BUFFER_INTERFACE(uint8_t) + DECLARE_GET_BUFFER_INTERFACE(int16_t) + DECLARE_GET_BUFFER_INTERFACE(uint16_t) + DECLARE_GET_BUFFER_INTERFACE(int32_t) + DECLARE_GET_BUFFER_INTERFACE(uint32_t) + DECLARE_GET_BUFFER_INTERFACE(int64_t) + DECLARE_GET_BUFFER_INTERFACE(uint64_t) + DECLARE_GET_BUFFER_INTERFACE(wchar_t) + DECLARE_GET_BUFFER_INTERFACE(char) +#undef DECLARE_GET_BUFFER_INTERFACE + + template + struct SelectIGetBufferBase + { + }; + +#define SPECIALIZE_SELECT_GET_BUFFER(ELT_TYPE) \ + template<> \ + struct SelectIGetBufferBase \ + { \ + using BaseType = IGetBuffer_ ## ELT_TYPE; \ + }; + + SPECIALIZE_SELECT_GET_BUFFER(int8_t) + SPECIALIZE_SELECT_GET_BUFFER(uint8_t) + SPECIALIZE_SELECT_GET_BUFFER(int16_t) + SPECIALIZE_SELECT_GET_BUFFER(uint16_t) + SPECIALIZE_SELECT_GET_BUFFER(int32_t) + SPECIALIZE_SELECT_GET_BUFFER(uint32_t) + SPECIALIZE_SELECT_GET_BUFFER(int64_t) + SPECIALIZE_SELECT_GET_BUFFER(uint64_t) + SPECIALIZE_SELECT_GET_BUFFER(wchar_t) + SPECIALIZE_SELECT_GET_BUFFER(char) +#undef SPECIALIZE_SELECT_GET_BUFFER + + template + using IGetBuffer_t = typename SelectIGetBufferBase::BaseType; + + class IVisitor + { + public: + virtual ~IVisitor() {} + + virtual void VisitPrimitiveElement(int8_t &elt) = 0; + virtual void VisitPrimitiveElement(uint8_t &elt) = 0; + virtual void VisitPrimitiveElement(int16_t &elt) = 0; + virtual void VisitPrimitiveElement(uint16_t &elt) = 0; + virtual void VisitPrimitiveElement(int32_t &elt) = 0; + virtual void VisitPrimitiveElement(uint32_t &elt) = 0; + virtual void VisitPrimitiveElement(int64_t &elt) = 0; + virtual void VisitPrimitiveElement(uint64_t &elt) = 0; + virtual void VisitPrimitiveElement(wchar_t &elt) = 0; + virtual void VisitPrimitiveElement(char &elt) = 0; + + virtual void VisitPrimitiveCollection(IGetBuffer_t< int8_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< uint8_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< int16_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< uint16_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< int32_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< uint32_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< int64_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< uint64_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< wchar_t> &getBuffer) = 0; + virtual void VisitPrimitiveCollection(IGetBuffer_t< char> &getBuffer) = 0; + + virtual void VisitElement(class VisitorContext &) = 0; + virtual void VisitCollection(size_t &count, class VisitorContext &ctx) = 0; + }; + + template + class ImplementIVisitor : public IVisitor + { + void VisitPrimitiveElement(int8_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint8_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(int16_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint16_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(int32_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint32_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(int64_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(uint64_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(wchar_t &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + void VisitPrimitiveElement(char &elt) override { static_cast(this)->ImplementVisitPrimitiveElement(elt); } + + void VisitPrimitiveCollection(IGetBuffer_t< int8_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< int8_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< uint8_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< uint8_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< int16_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< int16_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< uint16_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< uint16_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< int32_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< int32_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< uint32_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< uint32_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< int64_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< int64_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< uint64_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< uint64_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< wchar_t> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< wchar_t>(getBuffer); } + void VisitPrimitiveCollection(IGetBuffer_t< char> &getBuffer) override { static_cast(this)->ImplementVisitPrimitiveCollection< char>(getBuffer); } + + void VisitElement(class VisitorContext &ctx) override + { + static_cast(this)->ImplementVisitElement(ctx); + } + + void VisitCollection(size_t &count, class VisitorContext &ctx) override + { + static_cast(this)->ImplementVisitCollection(count, ctx); + } + }; + +} // namespace ATG +#pragma endregion + +//-------------------------------------------------------------------------------------- +// Visitor Context is a stack machine used to implement a non-recursive class visitor +//-------------------------------------------------------------------------------------- +#pragma region Visitor Context +namespace ATG +{ + template class ClassVisitorActions; + + // Prevents redundant creation of ClassVisitors by caching a static pointer + // each time a new ClassVisitorTemplate is created. Rather then using an indefinite + // singleton instance for each one, this class also manages the lifetimes + // and will delete the class visitors when it is destructed. + class ClassVisitorCache + { + // Only need a virtual destructor + class IHolder { public: virtual ~IHolder() {} }; + + // This class keeps track of the address of a static pointer + // The purpose of this class is to delete the object and then + // clear the pointer + template + class VisitorActionsHolder : public IHolder + { + public: + VisitorActionsHolder(T **visitorActions) + : m_visitorActions(visitorActions) + { + } + + ~VisitorActionsHolder() + { + if (m_visitorActions) + { + T *actions = *m_visitorActions; + *m_visitorActions = nullptr; + m_visitorActions = nullptr; + delete(actions); + } + } + + private: + T **m_visitorActions; + }; + + public: + + template + ClassVisitorActions &GetClassVisitor() + { + static ClassVisitorActions *cached = nullptr; + if (!cached) + { + cached = new ClassVisitorActions; + *cached = CreateClassVisitor(); + m_cleanupActions.emplace_back(new VisitorActionsHolder>(&cached)); + } + return *cached; + } + + private: + std::vector> m_cleanupActions; + }; + + class IResolvedAction + { + public: + virtual ~IResolvedAction() {} + virtual IResolvedAction *GetNext() const = 0; + virtual void Execute(class ResolvedActionContext &) = 0; + }; + + + template + class ResolvedAction : public IResolvedAction + { + public: + using ActionVecType = std::vector>::ActTyp>; + + ResolvedAction(T &instance, unsigned int currentAction, const ActionVecType &actions) + : m_instance(instance) + , m_currentAction(currentAction) + , m_actions(actions) + { + } + + IResolvedAction *GetNext() const override + { + if (m_actions.size() == 0) + { + return nullptr; + } + + if (m_currentAction == m_actions.size() - 1) + { + return nullptr; + } + + return new ResolvedAction(m_instance, m_currentAction + 1, m_actions); + } + + void Execute(ResolvedActionContext &ctx) override + { + ExecuteImpl(ctx); + } + + private: + template + void ExecuteImpl(CtxType &ctx) + { + if (m_actions.size() > 0) + { + m_actions[m_currentAction].Visit(m_instance, ctx); + } + } + + T &m_instance; + const unsigned int m_currentAction; + const ActionVecType &m_actions; + }; + + template + class ResolvedCollectionAction : public IResolvedAction + { + public: + using ActionVecType = std::vector>::ActTyp>; + + ResolvedCollectionAction( + size_t instanceCount, + T *instances, + unsigned int currentAction, + const ActionVecType &actions) + : m_instanceCount(instanceCount) + , m_instances(instances) + , m_currentAction(currentAction) + , m_actions(actions) + { + assert(m_instanceCount != 0); + } + + IResolvedAction *GetNext() const override + { + if (m_actions.size() == 0 || m_currentAction == m_actions.size() - 1) + { + size_t nextInstanceCount = m_instanceCount - 1; + if (nextInstanceCount == 0) + { + return nullptr; + } + + return new ResolvedCollectionAction( + nextInstanceCount, + m_instances + 1, + 0, + m_actions); + } + + return new ResolvedCollectionAction( + m_instanceCount, + m_instances, + m_currentAction + 1, + m_actions); + } + + void Execute(ResolvedActionContext &ctx) override + { + ExecuteImpl(ctx); + } + + private: + template + void ExecuteImpl(CtxType &ctx) + { + if (m_actions.size() > 0) + { + m_actions[m_currentAction].Visit(*m_instances, ctx); + } + } + + const size_t m_instanceCount; + T *m_instances; + const unsigned int m_currentAction; + const ActionVecType &m_actions; + }; + + template + class DoNextAction : public IResolvedAction + { + public: + DoNextAction(DoNextType doNext) + : m_doNext{ doNext } + { + } + + IResolvedAction *GetNext() const override + { + return nullptr; + } + + void Execute(ResolvedActionContext &) override + { + m_doNext(); + } + + private: + DoNextType m_doNext; + }; + + class ResolvedActionContext + { + public: + ResolvedActionContext() + { + } + + virtual ~ResolvedActionContext() + { + while (!m_stack.empty()) + { + delete m_stack.top(); + m_stack.pop(); + } + } + + template + void Push(T &inst) + { + auto& classVisitorActions = m_cache.GetClassVisitor>(); + auto& actions = classVisitorActions.GetActions(); + m_stack.push(new ResolvedAction(inst, 0, actions)); + } + + template + void PushCollection(T *instances, size_t count) + { + if (count == 0) return; + + auto& classVisitorActions = m_cache.GetClassVisitor>(); + auto& actions = classVisitorActions.GetActions(); + m_stack.push(new ResolvedCollectionAction(count, instances, 0, actions)); + } + + template + void Next(DoNextType doNext) + { + m_stack.push(new DoNextAction(doNext)); + } + + void Visit() + { + while (!m_stack.empty()) + { + { + std::unique_ptr firstAction(m_stack.top()); + m_stack.pop(); + IResolvedAction *nextAction = firstAction->GetNext(); + if (nextAction) + { + m_stack.push(nextAction); + } + firstAction->Execute(*this); + } + } + } + + protected: + ClassVisitorCache m_cache; + std::stack m_stack; + }; + + class VisitorContext : public ResolvedActionContext + { + private: + + template + class ContinuationAction : public IResolvedAction + { + public: + ContinuationAction(ContType cont) + : m_continuation(cont) + { + } + + IResolvedAction *GetNext() const override + { + return nullptr; + } + + void Execute(ResolvedActionContext &) override + { + m_continuation(result); + } + + T &GetResult() const + { + return m_result; + } + + private: + T m_result; + ContType m_continuation; + }; + + public: + VisitorContext(IVisitor &visitor) + : m_visitor(visitor) + { + } + + ~VisitorContext() + { + } + + IVisitor &GetVisitor() const + { + return m_visitor; + } + + template + void PushContinuation(ContType K) + { + ContinuationAction *contAction = new ContinuationAction(K); + m_stack.push(contAction); + Push(contAction->GetResult()); + } + + private: + IVisitor &m_visitor; + }; + + class ConstVisitorContext : public ResolvedActionContext + { + public: + ConstVisitorContext(IConstVisitor &visitor) + : m_visitor(visitor) + { + } + + ~ConstVisitorContext() + { + } + + IConstVisitor &GetVisitor() const + { + return m_visitor; + } + + private: + IConstVisitor &m_visitor; + }; +} // namespace ATG +#pragma endregion + +//-------------------------------------------------------------------------------------- +// Class Visitor enables a simple, declarative specification for "visiting" a class +//-------------------------------------------------------------------------------------- +#pragma region Class Visitor +namespace ATG +{ + class VisitorAdapter + { + template + class IGetBufferFromArray : public IGetBuffer_t + { + public: + IGetBufferFromArray(EltType(&a)[SIZE_]) + : m_a(a) + { + } + + EltType *GetBuffer(size_t count) override + { + if (count != SIZE_) + { + throw std::range_error("Wrong number of elements for fixed sized array"); + } + return &m_a[0]; + } + + private: + EltType(&m_a)[SIZE_]; + }; + + template + class IGetBufferFromOwner : public IGetBuffer_t + { + public: + IGetBufferFromOwner(T &owner, Callable &callable) + : m_owner(owner) + , m_callable(callable) + { + } + + EltType *GetBuffer(size_t count) override + { + return m_callable(m_owner, count); + } + + private: + T &m_owner; + Callable m_callable; + }; + + public: + VisitorAdapter(VisitorContext &ctx) + : m_ctx(ctx) + { + } + + template + void VisitMember(T& val) + { + m_ctx.GetVisitor().VisitPrimitiveElement(val); + } + + template + void VisitMember(T& val) + { + m_ctx.GetVisitor().VisitElement(m_ctx); + m_ctx.Push(val); + } + + template + void VisitMember(EltType(&a)[SIZE_]) + { + IGetBufferFromArray getBuffer(a); + m_ctx.GetVisitor().VisitPrimitiveCollection(getBuffer); + } + + template + void VisitMember(EltType(&a)[SIZE_]) + { + size_t eltCount = 0; + m_ctx.GetVisitor().VisitCollection(eltCount, m_ctx); + if (eltCount != SIZE_) + { + throw std::range_error("Wrong number of elements for fixed sized array"); + } + m_ctx.PushCollection(&a[0], SIZE_); + } + + template + void VisitSetter(T &inst, SetActionTy_ setter) + { + ValTy_ val; + m_ctx.GetVisitor().VisitPrimitiveElement(val); + setter(inst, val); + } + + template + void VisitSetter(T &inst, SetActionTy_ setter) + { + m_ctx.PushContinuation([&inst](ValTy_ &val) { + setter(inst, val); + }); + } + + template + void VisitCollection(T& inst, Callable setter) + { + IGetBufferFromOwner getBuffer(inst, setter); + m_ctx.GetVisitor().VisitPrimitiveCollection(getBuffer); + } + + template + void VisitCollection(T& inst, Callable setter) + { + size_t eltCount = 0; + m_ctx.GetVisitor().VisitCollection(eltCount, m_ctx); + EltType *elts = setter(inst, eltCount); + m_ctx.PushCollection(elts, eltCount); + } + + private: + VisitorContext &m_ctx; + }; + + class ConstVisitorAdapter + { + public: + ConstVisitorAdapter(ConstVisitorContext &ctx) + : m_ctx(ctx) + { + } + + template + void VisitMember(const T& val) + { + m_ctx.GetVisitor().VisitPrimitiveElement(val); + } + + template + void VisitMember(const T& val) + { + m_ctx.GetVisitor().VisitElement(m_ctx); + m_ctx.Push(val); + } + + template + void VisitMember(const EltType(&a)[SIZE_]) + { + m_ctx.GetVisitor().VisitPrimitiveCollection(a, SIZE_); + } + + template + void VisitMember(const EltType(&a)[SIZE_]) + { + m_ctx.GetVisitor().VisitCollection(SIZE_, m_ctx); + m_ctx.PushCollection(&a[0], SIZE_); + } + + template + void VisitGetter(const T &inst, GetActionTy_ getter) + { + ValTy_ val = getter(inst); + m_ctx.GetVisitor().VisitPrimitiveElement(val); + } + + template + void VisitGetter(const T &inst, GetActionTy_ getter) + { + ValTy_ val = getter(inst); + m_ctx.Push(val); + } + + template + void VisitCollection(const T& inst, Callable getter) + { + size_t count = 0; + const EltType* elts = getter(inst, count); + m_ctx.GetVisitor().VisitPrimitiveCollection(elts, count); + } + + template + void VisitCollection(const T& inst, Callable getter) + { + size_t count = 0; + const EltType* elts = getter(inst, count); + m_ctx.GetVisitor().VisitCollection(count, m_ctx); + m_ctx.PushCollection(elts, count); + } + + private: + ConstVisitorContext &m_ctx; + }; + + template + class ClassVisitorActions + { + private: + + class IClassVisitorActionImpl + { + public: + virtual ~IClassVisitorActionImpl() {} + virtual void VisitAction(T &inst, VisitorContext &ctx) const = 0; + virtual void ConstVisitAction(const T &inst, ConstVisitorContext &ctx) const = 0; + }; + + template + class ImplementIClassVisitor : public HasVisitActions, public IClassVisitorActionImpl + { + public: + using HasVisitActions::HasVisitActions; + + void VisitAction(T &inst, VisitorContext &ctx) const override + { + static_cast(this)->VisitAction(inst, ctx); + } + + void ConstVisitAction(const T &inst, ConstVisitorContext &ctx) const + { + static_cast(this)->ConstVisitAction(inst, ctx); + } + }; + + public: + template + class ClassVisitorAction + { + public: + template + struct P2Mmbr + { + typedef MmbrTyp T::*ptr; + }; + + ClassVisitorAction(IClassVisitorActionImpl *impl) + : m_impl(impl) + { + } + + ClassVisitorAction(ClassVisitorAction &&rhs) + : m_impl(std::move(rhs.m_impl)) + { + } + + ClassVisitorAction &operator=(ClassVisitorAction &&rhs) + { + m_impl = std::move(rhs.m_impl); + return *this; + } + + ClassVisitorAction(const ClassVisitorAction &) = delete; + ClassVisitorAction& operator=(const ClassVisitorAction &) = delete; + + void Visit(T &inst, class ResolvedActionContext &ctx) const + { + m_impl->VisitAction(inst, static_cast(ctx)); + } + + void Visit(const T &inst, class ResolvedActionContext &ctx) const + { + m_impl->ConstVisitAction(inst, static_cast(ctx)); + } + + private: + std::unique_ptr m_impl; + }; + + typedef ClassVisitorAction ActTyp; + + template + void AddVisitorAction(Args... args) + { + auto action = new ImplementIClassVisitor(args...); + m_actions.emplace_back(std::move(action)); + } + + const std::vector &GetActions() const + { + return m_actions; + } + + private: + std::vector m_actions; + }; + + // Visit the class with Direct access to the IVisitor/IConstVisitor + // This gives you the most direct access to the class and visitor + // E.g. use this perform extra step(s) after visiting a specific class member + // E.g. perform extra side-effects on the visitor that aren't directly tied to a single class member + // E.g. perform extra side-effects on the class etc. + // E.g. Establish class invariants after a destructive visit to the class + // E.g. Utilize the visitor without consuming/modifying data from the class + // Type Parameters: + // ClassType -- Type of the class to visit + // ConstVisitorCallable -- Type of a callable object (e.g. function pointer, functor, lambda, etc.) + // that performs side effect when this action is visited. (Does not perform + // a destructive action on the class.) + // E.g. void (*) (const ClassType &, IConstVisitor &); + // VisitorCallable -- Type of a callable object (e.g. funciton pointer, functor, lambda, etc.) + // that performs a side effect when this action is visited. (Can perform a + // a destructive action on the class.) + // E.g. void (*) (ClassType &, IVisitor &) + // + // Normal Parameters: + // constVisitorCallable -- Callable that consumes a const reference to the class and a reference to + // the IConstVistior that is visiting the class. + // visitorCallable -- Callable that consumes a (non-const) reference to the class and a reference + // to the IVisitor that is visiting the class. + template + class VisitDirectActions + { + public: + VisitDirectActions(ConstVisitorCallable constVisitorCallable, VisitorCallable visitorCallable) + : m_constVisitorCallable(constVisitorCallable) + , m_visitorCallable(visitorCallable) + { + } + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + m_visitorCallable(inst, ctx.GetVisitor()); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext &ctx) const + { + m_constVisitorCallable(inst, ctx.GetVisitor()); + } + + private: + ConstVisitorCallable m_constVisitorCallable; + VisitorCallable m_visitorCallable; + }; + + template + void VisitDirect(ClassVisitorActions &actions, ConstVisitorCallable constVisitorCallable, VisitorCallable visitorCallable) + { + actions.AddVisitorAction>(constVisitorCallable, visitorCallable); + } + + // Visit a class member + // Type Parameters: + // ClassType -- Type of the class whose member will be visited + // MmbrType -- Type of the member to visit + // + // Normal Parameters: + // mbr -- pointer-to-member for the class member to visit + template + class VisitMemberAction + { + public: + VisitMemberAction(MmbrType ClassType::*mbr) + : m_mbr(mbr) + { + } + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitMember(inst.*m_mbr); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext &ctx) const + { + ConstVisitorAdapter(ctx).VisitMember(inst.*m_mbr); + } + + private: + MmbrType ClassType::*m_mbr; + }; + + template + void VisitMember(ClassVisitorActions &actions, MmbrType ClassType::*mbr) + { + actions.AddVisitorAction>(mbr); + } + + // Visit a collection of elements that is pointed to by a unique_ptr + // Type Parameters: + // ClassType -- Type of the class that owns the unique_ptr. + // EltType -- Type of the elements pointed to by the unique_ptr. + // CountType -- Type of the class member that stores the element count. + // + // Normal Parameters: + // UUP -- pointer-to-member of type unique_ptr. The unique_ptr member points to the elements that will be visited. + // count -- pointer-to-member that holds the count of objects in the collection. + template + class VisitUniquePointerCollectionAction + { + public: + VisitUniquePointerCollectionAction(std::unique_ptr ClassType::*UPP, CountType ClassType::*count) + : m_UPP(UPP) + , m_count(count) + {} + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitCollection(inst, *this); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext &ctx) const + { + ConstVisitorAdapter(ctx).VisitCollection(inst, *this); + } + + EltType *operator()(ClassType &inst, size_t eltCount) + { + auto& UP = inst.*m_UPP; + inst.*m_count = CountType(eltCount); + UP.reset(new EltType[eltCount]); + return UP.get(); + } + + const EltType *operator()(const ClassType &inst, size_t &eltCount) + { + eltCount = inst.*m_count; + auto& UP = inst.*m_UPP; + return UP.get(); + } + + private: + std::unique_ptr ClassType::*m_UPP; + CountType ClassType::*m_count; + }; + + template + void VisitUniquePointerCollection(ClassVisitorActions &actions, std::unique_ptr ClassType::*UPP, CountType ClassType::*count) + { + actions.AddVisitorAction>(UPP, count); + } + + // Visit one or zero elements pointed to by a unique_ptr + // Type Parameters: + // ClassType -- Type of the class that owns the unique_ptr. + // EltType -- Type of the elements pointed to by the unique_ptr. + // + // Normal Parameters: + // UUP -- pointer-to-member of type unique_ptr. The unique_ptr member points to the elements that will be visited. + template + class VisitNullableUniquePtrAction + { + public: + VisitNullableUniquePtrAction(std::unique_ptr ClassType::*UPP) + : m_UPP(UPP) + { + } + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitCollection(inst, *this); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext & ctx) const + { + ConstVisitorAdapter(ctx).VisitCollection(inst, *this); + } + + EltType *operator()(ClassType &inst, size_t eltCount) + { + auto& UP = inst.*m_UPP; + if (eltCount == 0) + { + UP = nullptr; + } + else + { + assert(eltCount == 1); + UP.reset(new EltType); + } + return UP.get(); + } + + const EltType *operator()(const ClassType &inst, size_t &eltCount) + { + auto& UP = inst.*m_UPP; + auto result = UP.get(); + eltCount = result == nullptr ? 0 : 1; + return result; + } + + private: + std::unique_ptr ClassType::*m_UPP; + }; + + template + void VisitNullableUniquePointer(ClassVisitorActions &actions, std::unique_ptr ClassType::*UPP) + { + actions.AddVisitorAction>(UPP); + } + + // Visit a collection of elements contained in a std::vector + // Type Parameters: + // ClassType -- Type of the class that owns the vector. + // EltType -- Type of the elements contained in the vector. + // + // Normal Parameters: + // VecP -- pointer-to-member of type vector that contains the elements that will be visited. + template + class VisitVectorCollectionAction + { + public: + VisitVectorCollectionAction(std::vector ClassType::*VecP) + : m_VecP(VecP) + { + } + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitCollection(inst, *this); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext & ctx) const + { + ConstVisitorAdapter(ctx).VisitCollection(inst, *this); + } + + EltType *operator()(ClassType &inst, size_t eltCount) + { + auto& vec = inst.*m_VecP; + vec.clear(); + vec.resize(eltCount); + return eltCount ? &vec[0] : nullptr; + } + + const EltType *operator()(const ClassType &inst, size_t &eltCount) + { + auto& vec = inst.*m_VecP; + eltCount = vec.size(); + return eltCount ? &vec[0] : nullptr; + } + + private: + std::vector ClassType::*m_VecP; + }; + + template + void VisitVectorCollection(ClassVisitorActions &actions, std::vector ClassType::*VecP) + { + actions.AddVisitorAction>(VecP); + } + + // Visit a collection of chars contained in a std::string + // Type Parameters: + // ClassType -- Type of the class that owns the string. + // Normal Parameters: + // VecP -- pointer-to-member of type string that will be visited. + template + class VisitStringAction + { + public: + VisitStringAction(std::string ClassType::*StrP) + : m_StrP(StrP) + { + } + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitCollection(inst, *this); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext &ctx) const + { + ConstVisitorAdapter(ctx).VisitCollection(inst, *this); + } + + char *operator()(ClassType &inst, size_t eltCount) + { + auto& str = inst.*m_StrP; + str.clear(); + str.resize(eltCount); + return &str[0]; + } + + const char *operator()(const ClassType &inst, size_t &eltCount) + { + auto& str = inst.*m_StrP; + eltCount = str.size(); + return str.c_str(); + } + + private: + std::string ClassType::*m_StrP; + }; + + template + void VisitString(ClassVisitorActions &actions, std::string ClassType::*StrP) + { + actions.AddVisitorAction>(StrP); + } + + // Visit a collection of elements using functions to get and set the collection elements + // Type Parameters: + // ClassType -- Type of the class that owns the collection. + // EltType -- Type of the elements contained in the collection. + // ConstEltsCallable -- Type of callable object (e.g. function pointer, functor, lambda, etc.) to retrieve + // the size of the collection as well as a pointer to the collection elements. + // E.g. const EltType *(*)(const ClassType &, size_t &) + // Notice that it returns a pointer to the elements and modifies the size_t argument + // EltsCallable -- Type of callable object (e.g. function pointer, functor, lambda, etc.) to retrieve + // a pointer to an array of new elements of the requested size. + // E.g. EltType *(*)(ClasType&, size_t) + // Notice that it returns a pointer to the memory containg the new elements and consumes + // the count of new elements located in the memory location + // + // Normal Parameters: + // constEltsGetter -- Callable to retrieve the size of the collection as well as a pointer to the colleciton elements + // eltsSetter -- Callable to retrieve a pointer to memory containing the requested count of new elements + template + class VisitCollectionWithFunctionsAction + { + public: + VisitCollectionWithFunctionsAction(ConstEltsCallable constEltsGetter, EltsCallable eltsSetter) + : m_constEltsGetter(constEltsGetter) + , m_eltsSetter(eltsSetter) + {} + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitCollection(inst, m_eltsSetter); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext &ctx) const + { + ConstVisitorAdapter(ctx).VisitCollection(inst, m_constEltsGetter); + } + + private: + ConstEltsCallable m_constEltsGetter; + EltsCallable m_eltsSetter; + }; + + template + void VisitCollectionWithFunctions(ClassVisitorActions &actions, ConstEltsCallable constEltsGetter, EltsCallable eltsSetter) + { + actions.AddVisitorAction>(constEltsGetter, eltsSetter); + } + + // Visit a class member using a getter function and setter function + // Type Paramerts + // ClassType -- type of the class to visit + // EltType -- type of the element retrieved and set byt the getter and setter + // GetActionType -- callable for getting a value of type EltType from the instance of ClassType + // SetActionType -- callable for setting a value of type EltType within the instance of ClassType + // + // Normal Parameters: + // getter -- get a value of type EltType from the class instance + // setter -- set a avlue of type EltType within the class instance + template + class VisitGetterSetterAction + { + public: + + VisitGetterSetterAction(GetActionType getter, SetActionType setter) + : m_getter(getter) + , m_setter(setter) + { + } + + void VisitAction(ClassType &inst, VisitorContext &ctx) const + { + VisitorAdapter(ctx).VisitSetter(inst, m_setter); + } + + void ConstVisitAction(const ClassType &inst, ConstVisitorContext & ctx) const + { + ConstVisitorAdapter(ctx).VisitGetter(inst, m_getter); + } + + private: + GetActionType m_getter; + SetActionType m_setter; + }; + + template + void VisitGetterSetter(ClassVisitorActions &actions, GetActionType getter, SetActionType setter) + { + actions.AddVisitorAction>(getter, setter); + } + + // Template function to create a class visitor for your class + // By default, it assumes that you have a static CreateClassVisitor method + // however, you can specialize this function in the case when you dont want + // to or cannot add a static method to your class. + template + ClassVisitorActions CreateClassVisitor() + { + return T::CreateClassVisitor(); + } + +} // namespace ATG +#pragma endregion + +//-------------------------------------------------------------------------------------- +// Serialization +// Implements serialization using the generic visitor implementation +//-------------------------------------------------------------------------------------- +#pragma region Serialization +namespace ATG +{ + class FixedSizeSerializationBuffer + { + public: + FixedSizeSerializationBuffer(uint8_t *outputBuffer, size_t outputBufferSize) + : m_bytesWritten(0) + , m_outputBufferSize(outputBufferSize) + , m_outputBuffer(outputBuffer) + { + } + + size_t GetBytesWritten() const + { + return m_bytesWritten; + } + + template + void WriteIntegers(const T *vals, size_t count) + { + size_t bytesRemaining = m_outputBufferSize - m_bytesWritten; + size_t requiredSize = sizeof(T) * count; + if (bytesRemaining < requiredSize) + { + throw std::overflow_error("Output buffer is too small to receive the expected data."); + } + if(count > 0) + memcpy_s(&m_outputBuffer[m_bytesWritten], bytesRemaining, vals, requiredSize); + m_bytesWritten += requiredSize; + } + + private: + size_t m_bytesWritten; + const size_t m_outputBufferSize; + uint8_t *m_outputBuffer; + }; + + class StreamSerializationBuffer + { + public: + StreamSerializationBuffer(std::basic_ostream &strm) + : m_bytesWritten(0) + , m_stream(strm) + { + } + + size_t GetBytesWritten() const + { + return m_bytesWritten; + } + + template + void WriteIntegers(const T *vals, size_t count) + { + size_t requiredSize = sizeof(T) * count; + m_stream.write(reinterpret_cast(vals), requiredSize); + m_bytesWritten += requiredSize; + } + + private: + size_t m_bytesWritten; + std::basic_ostream &m_stream; + }; + + class VectorSerializationBuffer + { + public: + VectorSerializationBuffer(std::vector &buffer) + : m_buffer(buffer) + , m_bytesWritten(0) + { + } + + size_t GetBytesWritten() const + { + return m_bytesWritten; + } + + template + void WriteIntegers(const T *vals, size_t count) + { + size_t requiredSize = sizeof(T) * count; + m_buffer.resize(m_bytesWritten + requiredSize); + if(count > 0) + memcpy_s(&m_buffer[m_bytesWritten], requiredSize, vals, requiredSize); + m_bytesWritten += requiredSize; + } + + private: + size_t m_bytesWritten; + std::vector &m_buffer; + }; + + // -------------------------------------------------------------------------------- + // Serializing to Output + // -------------------------------------------------------------------------------- + template + class Serializer : public ImplementIConstVisitor> + { + public: + Serializer(buffer_t &serializationBuffer) + : m_serializationBuffer(serializationBuffer) + { + } + + // Serialize a simple integral type + template + void ImplementVisitPrimitiveElement(T val) + { + m_serializationBuffer.WriteIntegers(&val, 1); + } + + template + void ImplementVisitPrimitiveCollection(const EltType *elts, size_t count) + { + // Serialize the element count + ImplementVisitPrimitiveElement(count); + + // Serialize the elements + m_serializationBuffer.WriteIntegers(elts, count); + } + + void ImplementVisitCollection(size_t count, class ConstVisitorContext &) + { + // Serialize the element count + ImplementVisitPrimitiveElement(count); + } + + void ImplementVisitElement(class ConstVisitorContext &) + { + } + + private: + buffer_t &m_serializationBuffer; + }; + + template + size_t Serialize(const T &serializeMe, buffer_t &srzBffr) + { + Serializer srzr(srzBffr); + ConstVisitorContext ctx(srzr); + ctx.Push(serializeMe); + ctx.Visit(); + return srzBffr.GetBytesWritten(); + } + + template + size_t Serialize(const T &serializeMe, uint8_t *outputBuffer, size_t outputBufferSize) + { + FixedSizeSerializationBuffer srzBffr(outputBuffer, outputBufferSize); + return Serialize(serializeMe, srzBffr); + } + +} // namespace ATG +#pragma endregion + +//-------------------------------------------------------------------------------------- +// Deserialization +// Implements deserialization using the generic visitor implementation +//-------------------------------------------------------------------------------------- +#pragma region Deserialization +namespace ATG +{ + class FixedSizeDeserializationBuffer + { + public: + FixedSizeDeserializationBuffer(const uint8_t *inputBuffer, size_t inputBufferSize) + : m_bytesRead(0) + , m_inputBufferSize(inputBufferSize) + , m_inputBuffer(inputBuffer) + { + } + + size_t GetBytesRead() const + { + return m_bytesRead; + } + + template + void ReadIntegers(T *vals, size_t count) + { + size_t bytesRemaining = m_inputBufferSize - m_bytesRead; + size_t requiredSize = sizeof(T) * count; + if (bytesRemaining < requiredSize) + { + throw std::overflow_error("Input buffer is too small to contain the expected data."); + } + memcpy_s(vals, requiredSize, &m_inputBuffer[m_bytesRead], requiredSize); + m_bytesRead += requiredSize; + } + + private: + size_t m_bytesRead; + const size_t m_inputBufferSize; + const uint8_t *m_inputBuffer; + }; + + class StreamDeserializationBuffer + { + public: + StreamDeserializationBuffer(std::basic_istream &strm) + : m_bytesRead(0) + , m_stream(strm) + { + } + + size_t GetBytesRead() const + { + return m_bytesRead; + } + + template + void ReadIntegers(T *vals, size_t count) + { + size_t requiredSize = sizeof(T) * count; + m_stream.read(reinterpret_cast(vals), requiredSize); + m_bytesRead += requiredSize; + } + + private: + size_t m_bytesRead; + std::basic_istream &m_stream; + }; + + // -------------------------------------------------------------------------------- + // Deserializing from Input + // -------------------------------------------------------------------------------- + template + class Deserializer : public ImplementIVisitor> + { + public: + Deserializer(buffer_t &deserializationBuffer) + : m_deserializationBuffer(deserializationBuffer) + { + } + + // Deserialize a simple integral type + template + void ImplementVisitPrimitiveElement(T &val) + { + m_deserializationBuffer.ReadIntegers(&val, 1); + } + + // Deserialize a collection of elements of integral type + template + void ImplementVisitPrimitiveCollection(IGetBuffer_t &getBuffer) + { + // Deserialize the size + size_t eltCount = 0; + ImplementVisitPrimitiveElement(eltCount); + + EltType *elts = getBuffer.GetBuffer(eltCount); + + // Deserialize the elements + m_deserializationBuffer.ReadIntegers(elts, eltCount); + } + + void ImplementVisitCollection(size_t &count, class VisitorContext &) + { + // Deserialize the element count + ImplementVisitPrimitiveElement(count); + } + + void ImplementVisitElement(class VisitorContext &) + { + } + + private: + buffer_t &m_deserializationBuffer; + }; + + template + size_t Deserialize(T &deserializeMe, buffer_t &dsrzBffr) + { + Deserializer dsrzr(dsrzBffr); + VisitorContext ctx(dsrzr); + ctx.Push(deserializeMe); + ctx.Visit(); + return dsrzBffr.GetBytesRead(); + } + + template + size_t Deserialize(T &deserializeMe, const uint8_t *inputBuffer, size_t inputBufferSize) + { + FixedSizeDeserializationBuffer dsrzBffr(inputBuffer, inputBufferSize); + return Deserialize(deserializeMe, dsrzBffr); + } + +} // namespace ATG +#pragma endregion + + +//-------------------------------------------------------------------------------------- +// Serialization Header +// File header to be serialized/deserialized to track the serialization version and +// endianness +//-------------------------------------------------------------------------------------- +#pragma region Serialization Header +namespace ATG +{ +#define SERIALIZATION_CURRENT_VERSION_STRING "v0.1" + + class SerializationHeader + { + public: + enum SerializationFlags : uint32_t + { + none = 0, + is_host_endian = 1, + is_current_version = 2, + }; + + static ClassVisitorActions CreateClassVisitor() + { + ClassVisitorActions actions; + + // Serialize the version string + VisitString(actions, &SerializationHeader::m_verString); + + // Set the version flag based on the version string + VisitDirect(actions, + [](const SerializationHeader &, IConstVisitor&) {}, + [](SerializationHeader &header, IVisitor&) + { + uint32_t flags = static_cast(header.m_flags); + const uint32_t isCurrentVersion = static_cast(SerializationHeader::SerializationFlags::is_current_version); + + if (header.m_verString == SERIALIZATION_CURRENT_VERSION_STRING) + { + flags |= isCurrentVersion; + } + else + { + flags &= ~isCurrentVersion; + } + + header.m_flags = static_cast(flags); + }); + + // Serialize/Deserialize a byte order mark and adjust the flags accordingly + VisitGetterSetter( + actions, + [](const SerializationHeader &) + { + return wchar_t(0xFEFF); // Deliver the byte-order-mark to the serializer + }, + [](SerializationHeader &header, wchar_t BOM) + { + // Consume the byte-order-mark from the visitor and then adjust the flags accordingly + uint32_t flags = static_cast(header.m_flags); + const uint32_t isHostEndianFlag = static_cast(SerializationHeader::SerializationFlags::is_host_endian); + switch (BOM) + { + case 0xFEFF: + flags |= isHostEndianFlag; // Bytes occur in host order + break; + + case 0xFFFE: + flags &= ~isHostEndianFlag; // Bytes are swapped (not host order) + break; + + default: + throw std::invalid_argument("Unrecognized byte-order-mark in serialization stream"); + } + header.m_flags = static_cast(flags); + }); + + return actions; + } + + SerializationHeader() + : m_verString(SERIALIZATION_CURRENT_VERSION_STRING) + , m_flags(SerializationFlags::none) + { + } + + const char *GetVersion() const + { + return m_verString.c_str(); + } + + SerializationFlags GetFlags() const + { + return m_flags; + } + + bool CheckFlag(SerializationFlags flag) const + { + uint32_t flagVal = static_cast(flag); + uint32_t flagsVal = static_cast(m_flags); + + return ((flagsVal & flagVal) == flagVal); + } + + private: + std::string m_verString; + SerializationFlags m_flags; + }; + +} // namespace ATG +#pragma endregion \ No newline at end of file diff --git a/Kits/ATGTK/ThreadHelpers.h b/Kits/ATGTK/ThreadHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..e53336acf314915717149b72805c843939de48b0 --- /dev/null +++ b/Kits/ATGTK/ThreadHelpers.h @@ -0,0 +1,203 @@ +//-------------------------------------------------------------------------------------- +// File: ThreadHelpers.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +namespace DX +{ + class ThreadSuspender + { + private: + HANDLE m_hThread; + + public: + ThreadSuspender(HANDLE hThread) + : m_hThread(hThread) + { + SuspendThread(m_hThread); + } + + ~ThreadSuspender() + { + ResumeThread(m_hThread); + } + }; + + // Sets a thread name for debugging and profiling + template + inline void SetThreadName(HANDLE hThread, _In_z_ const char(&name)[TNameLength]) + { +#if defined(_XBOX_ONE) && defined(_TITLE) + wchar_t wname[MAX_PATH]; + int result = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, TNameLength, wname, MAX_PATH); + if (result > 0) + { + ::SetThreadName(hThread, wname); + } +#else + // See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx +#pragma pack(push,8) + typedef struct tagTHREADNAME_INFO + { + uint32_t dwType; + const char* szName; + uint32_t dwThreadID; + uint32_t dwFlags; + } THREADNAME_INFO; +#pragma pack(pop) + + DWORD threadId = GetThreadId(hThread); + + THREADNAME_INFO info = { 0x1000, name, !threadId ? uint32_t(-1) : threadId, 0 }; + +#pragma warning(push) +#pragma warning(disable: 6320 6322) + __try + { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (const ULONG_PTR*)&info); + } + __except (GetExceptionCode() == 0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER) + { + __noop; + } +#pragma warning(pop) +#endif + } + + class ThreadHelpers + { + ThreadHelpers() + { +#if defined(_XBOX_ONE) && defined(_TITLE) + +#elif defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP + ULONG retsize = 0; + (void)GetSystemCpuSetInformation(nullptr, 0, &retsize, GetCurrentProcess(), 0); + + m_cpuSetsInformation.reset(new uint8_t[retsize]); + + PSYSTEM_CPU_SET_INFORMATION cpuSets = reinterpret_cast(m_cpuSetsInformation.get()); + if (!GetSystemCpuSetInformation(cpuSets, retsize, &retsize, GetCurrentProcess(), 0)) + { + throw std::exception("GetSystemCpuSetInformation"); + } + + size_t count = retsize / cpuSets[0].Size; + + for (unsigned long i = 0; i < count; ++i) + { + if (cpuSets[i].Type == CpuSetInformation) + { + if (m_coresCollection.find(cpuSets[i].CpuSet.CoreIndex) == m_coresCollection.end()) + { + m_coresCollection.insert(std::pair(cpuSets[i].CpuSet.CoreIndex, &cpuSets[i])); + } + } + } +#else + + unsigned long length = 0; + (void)GetLogicalProcessorInformation(nullptr, &length); + + std::unique_ptr buffer(new uint8_t[length]); + + SYSTEM_LOGICAL_PROCESSOR_INFORMATION *procInfo = reinterpret_cast(buffer.get()); + if (!GetLogicalProcessorInformation(procInfo, &length)) + { + throw std::exception("GetLogicalProcessorInformation"); + } + + int count = length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + for (int i = 0; i < count; ++i) + { + if (procInfo[i].Relationship == RelationProcessorCore) + { + m_physicalCoreMaskLookup.push_back(procInfo[i].ProcessorMask); + } + } + +#endif + } + + public: + + ThreadHelpers(ThreadHelpers&&) = default; + ThreadHelpers& operator=(ThreadHelpers&&) = default; + + ThreadHelpers(const ThreadHelpers&) = delete; + ThreadHelpers& operator=(const ThreadHelpers&) = delete; + + void SetThreadPhysicalProcessor(HANDLE hThread, unsigned coreIndex) const + { +#if defined(_XBOX_ONE) && defined(_TITLE) + assert(coreIndex < 8); + SetThreadAffinityMask(hThread, uintptr_t(0x1) << coreIndex); +#elif defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP + if (coreIndex < GetCoreCount()) + { + auto iter = m_coresCollection.begin(); + while (coreIndex-- != 0) + ++iter; + + unsigned long physicalCore = m_coresCollection.at(iter->first)->CpuSet.Id; + + (void)SetThreadSelectedCpuSets(hThread, &physicalCore, 1); + } +#else + if (coreIndex < GetCoreCount()) + { + SetThreadAffinityMask(hThread, m_physicalCoreMaskLookup[coreIndex]); + } +#endif + } + + unsigned GetCoreCount() const + { +#if defined(_XBOX_ONE) && defined(_TITLE) + return 8; +#elif defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP + return static_cast(m_coresCollection.size()); +#else + return static_cast(m_physicalCoreMaskLookup.size()); +#endif + } + + static ThreadHelpers* Instance() + { + static ThreadHelpers s_instance; + return &s_instance; + } + + private: + +#if defined(_XBOX_ONE) && defined(_TITLE) + +#elif defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP + + std::unique_ptr m_cpuSetsInformation; + std::map m_coresCollection; + +#else + + std::vector m_physicalCoreMaskLookup; + +#endif + }; +} diff --git a/Kits/CPUTK/OSLockable.h b/Kits/CPUTK/OSLockable.h new file mode 100644 index 0000000000000000000000000000000000000000..e757e9dafa3bfe2dee21c1bf2701d24837f4a2a9 --- /dev/null +++ b/Kits/CPUTK/OSLockable.h @@ -0,0 +1,230 @@ +//-------------------------------------------------------------------------------------- +// OSLockable.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +// It's required to include the proper OS header based on target platform before including this header +#include +#include +#include + +// Provides wrappers around the standard Windows locking primitives to make them act like a C++ timedLockable +// This allowed them to all be used in any C++ thread interfaces + +namespace ATG +{ + ////////////////////////////////////////////////////////////////////////// + /// \brief EventLockable + /// \details ATG::EventLockable + /// \details Wraps a Windows Event object and implements the C++ concept TimedLockable + /// Can be used in all C++ thread interfaces + ////////////////////////////////////////////////////////////////////////// + template + class EventLockable + { + private: + HANDLE m_event; + + public: + EventLockable(const EventLockable&) = delete; + EventLockable& operator=(const EventLockable&) = delete; + + EventLockable() { m_event = CreateEvent(nullptr, manualReset, initialState, nullptr); if (!m_event) throw std::exception("CreateEvent failed"); } + EventLockable(EventLockable&& rhs) { m_event = rhs.m_event; rhs.m_event = INVALID_HANDLE_VALUE; } + ~EventLockable() { CloseHandle(m_event); } + + void wait() { lock(); } + void signal() { unlock(); } + + void lock() + { + WaitForSingleObject(m_event, INFINITE); + } + + bool try_lock() + { + return WaitForSingleObject(m_event, 0) == WAIT_OBJECT_0; + } + + void unlock() + { + SetEvent(m_event); + } + + void reset() + { + ResetEvent(m_event); + } + + template + bool try_lock_for(const std::chrono::duration<_Rep, _Period>& relTime) + { + int64_t msWait = std::chrono::duration_cast(relTime).count(); + if (msWait < 0) + msWait = 0; + msWait = static_cast (std::ceil(static_cast (msWait) / 1000000.0)); + + return WaitForSingleObject(m_event, static_cast (msWait)) == WAIT_OBJECT_0; + } + + template + bool try_lock_until(const std::chrono::time_point<_Clock, _Duration>& absTime) + { + return try_lock_for(absTime - std::chrono::steady_clock::now()); + } + }; + + ////////////////////////////////////////////////////////////////////////// + /// \brief SemaphoreLockable + /// \details ATG::SemaphoreLockable + /// \details Wraps a Windows Semaphore object and implements the C++ concept TimedLockable + /// Can be used in all C++ thread interfaces + ////////////////////////////////////////////////////////////////////////// + template + class SemaphoreLockable + { + private: + HANDLE m_semaphore; + + public: + SemaphoreLockable(const SemaphoreLockable&) = delete; + SemaphoreLockable& operator=(const SemaphoreLockable&) = delete; + + SemaphoreLockable() + { + m_semaphore = CreateSemaphoreEx(nullptr, initialCount, maximumCount, nullptr, 0, SYNCHRONIZE | SEMAPHORE_MODIFY_STATE); + if (!m_semaphore) + throw std::exception("CreateSemaphoreEx failed"); + } + SemaphoreLockable(SemaphoreLockable&& rhs) { m_semaphore = rhs.m_semaphore; rhs.m_semaphore = INVALID_HANDLE_VALUE; } + ~SemaphoreLockable() { CloseHandle(m_semaphore); } + + void wait() { lock(); } + void signal(uint32_t postCount = 1) { unlock(postCount); } + void post(uint32_t postCount = 1) { unlock(postCount); } + + void lock() + { + WaitForSingleObject(m_semaphore, INFINITE); + } + + bool try_lock() + { + return WaitForSingleObject(m_semaphore, 0) == WAIT_OBJECT_0; + } + + void unlock(uint32_t count = 1) + { + ReleaseSemaphore(m_semaphore, count, nullptr); + } + + template + bool try_lock_for(const std::chrono::duration<_Rep, _Period>& relTime) + { + int64_t msWait = std::chrono::duration_cast(relTime).count(); + if (msWait < 0) + msWait = 0; + return WaitForSingleObject(m_semaphore, static_cast (msWait)) == WAIT_OBJECT_0; + } + + template + bool try_lock_until(const std::chrono::time_point<_Clock, _Duration>& absTime) + { + return try_lock_for(absTime - std::chrono::steady_clock::now()); + } + }; + + ////////////////////////////////////////////////////////////////////////// + /// \brief MutexLockable + /// \details ATG::MutexLockable + /// \details Wraps a Windows Mutex object and implements the C++ concept TimedLockable + /// Can be used in all C++ thread interfaces + ////////////////////////////////////////////////////////////////////////// + class MutexLockable + { + private: + HANDLE m_mutex; + + public: + MutexLockable(const MutexLockable&) = delete; + MutexLockable& operator=(const MutexLockable&) = delete; + + MutexLockable() + { + m_mutex = CreateMutex(nullptr, false, nullptr); + if (!m_mutex) + throw std::exception("CreateMutex failed"); + } + MutexLockable(MutexLockable&& rhs) { m_mutex = rhs.m_mutex; rhs.m_mutex = INVALID_HANDLE_VALUE; } + ~MutexLockable() { CloseHandle(m_mutex); } + + void lock() + { + WaitForSingleObject(m_mutex, INFINITE); + } + + bool try_lock() + { + return WaitForSingleObject(m_mutex, 0) == WAIT_OBJECT_0; + } + + void unlock() + { + ReleaseMutex(m_mutex); + } + + template + bool try_lock_for(const std::chrono::duration<_Rep, _Period>& relTime) + { + int64_t msWait = std::chrono::duration_cast(relTime).count(); + if (msWait < 0) + msWait = 0; + return WaitForSingleObject(m_mutex, static_cast (msWait)) == WAIT_OBJECT_0; + } + + template + bool try_lock_until(const std::chrono::time_point<_Clock, _Duration>& absTime) + { + return try_lock_for(absTime - std::chrono::steady_clock::now()); + } + }; + + ////////////////////////////////////////////////////////////////////////// + /// \brief CriticalSectionLockable + /// \details ATG::CriticalSectionLockable + /// \details Wraps a Windows CRITICAL_SECTION object and implements the C++ concept Lockable + /// TimedLockable is not supported because CRITICAL_SECTION does not support + /// Can be used in all C++ thread interfaces + ////////////////////////////////////////////////////////////////////////// + class CriticalSectionLockable + { + private: + CRITICAL_SECTION m_critSection; + + public: + CriticalSectionLockable(const CriticalSectionLockable&) = delete; + CriticalSectionLockable& operator=(const CriticalSectionLockable&) = delete; + + CriticalSectionLockable(uint32_t spinCount = 0) { (void)InitializeCriticalSectionAndSpinCount(&m_critSection, spinCount); } + CriticalSectionLockable(CriticalSectionLockable&& rhs) = delete; + ~CriticalSectionLockable() { DeleteCriticalSection(&m_critSection); } + + void lock() + { + EnterCriticalSection(&m_critSection); + } + + bool try_lock() + { + return TryEnterCriticalSection(&m_critSection) == TRUE; + } + + void unlock() + { + LeaveCriticalSection(&m_critSection); + } + }; +} diff --git a/Kits/DirectXTK/DirectXTK_XboxOneXDK_2015.vcxproj b/Kits/DirectXTK/DirectXTK_XboxOneXDK_2015.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..2092ed12ba55485774af26d8630de61432b5624f --- /dev/null +++ b/Kits/DirectXTK/DirectXTK_XboxOneXDK_2015.vcxproj @@ -0,0 +1,621 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + + + + + + Document + + + + + Document + + + Document + + + + DirectXTK + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + StaticLibrary + v140 + false + Unicode + false + false + + + StaticLibrary + v140 + false + Unicode + false + false + + + StaticLibrary + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + DirectXTK + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + DirectXTK + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + DirectXTK + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib; + + + true + Windows + true + true + false + + + Use + pch.h + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;_LIB;%(PreprocessorDefinitions) + EnableAllWarnings + true + true + false + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib; + + + true + Windows + true + true + false + + + Use + pch.h + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;_LIB;PROFILE;%(PreprocessorDefinitions) + EnableAllWarnings + true + true + false + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib; + Windows + true + false + + + pch.h + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + EnableAllWarnings + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;_LIB;%(PreprocessorDefinitions) + false + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTK/DirectXTK_XboxOneXDK_2015.vcxproj.filters b/Kits/DirectXTK/DirectXTK_XboxOneXDK_2015.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..35463924368845484c95e47e81ec733066b332a7 --- /dev/null +++ b/Kits/DirectXTK/DirectXTK_XboxOneXDK_2015.vcxproj.filters @@ -0,0 +1,1255 @@ + + + + + {37d8d298-8ff7-4b16-9de2-1e8e5b943795} + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {1d7c612f-bf24-4368-a247-46d28920c4a7} + + + {5bfd0d52-ee7d-4cf1-aab2-235c7a1f9d6e} + + + {9fa25651-7bb5-42a1-b589-06be42c55e5b} + + + {bb66477f-d2e3-4eed-9c13-e86060685825} + + + {a6ee428c-85f6-4fea-979a-8c22779cd9e7} + + + {78fbbc63-3923-4adc-a469-79721986c80d} + + + + + Audio + + + Audio + + + Audio + + + Audio + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Src + + + Src + + + Src + + + Inc + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Inc\Shared + + + Inc\Shared + + + Inc\Shared + + + Inc\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Inc + + + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src + + + Src + + + Src + + + Src + + + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shared + + + Inc\Shared + + + Src\Shaders\Shared + + + Src\Shaders\Shared + + + Src\Shaders\Shared + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Shared + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTK/Inc/XboxDDSTextureLoader.h b/Kits/DirectXTK/Inc/XboxDDSTextureLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..e1e0481ee09bad1d830ac43f467fe2bb16fc0603 --- /dev/null +++ b/Kits/DirectXTK/Inc/XboxDDSTextureLoader.h @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// File: XboxDDSTextureLoader.h +// +// Functions for loading a DDS texture using the XBOX extended header and creating a +// Direct3D11.X runtime resource for it via the CreatePlacement APIs +// +// Note these functions will not load standard DDS files. Use the DDSTextureLoader +// module in the DirectXTex package or as part of the DirectXTK library to load +// these files which use standard Direct3D resource creation APIs. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#error This module only supports Xbox One exclusive apps +#endif + +#include + +#include + +namespace Xbox +{ + enum DDS_ALPHA_MODE + { + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, + }; + + HRESULT __cdecl CreateDDSTextureFromMemory( + _In_ ID3D11DeviceX* d3dDevice, + _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, + _In_ size_t ddsDataSize, + _Outptr_opt_ ID3D11Resource** texture, + _Outptr_opt_ ID3D11ShaderResourceView** textureView, + _Outptr_ void** grfxMemory, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _In_ bool forceSRGB = false); + + HRESULT __cdecl CreateDDSTextureFromFile( _In_ ID3D11DeviceX* d3dDevice, + _In_z_ const wchar_t* szFileName, + _Outptr_opt_ ID3D11Resource** texture, + _Outptr_opt_ ID3D11ShaderResourceView** textureView, + _Outptr_ void** grfxMemory, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _In_ bool forceSRGB = false); + + void FreeDDSTextureMemory( _In_opt_ void* grfxMemory ); +} \ No newline at end of file diff --git a/Kits/DirectXTK/Src/XboxDDSTextureLoader.cpp b/Kits/DirectXTK/Src/XboxDDSTextureLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de75a2380637fd2218e399fd39caa36eac6b7d7d --- /dev/null +++ b/Kits/DirectXTK/Src/XboxDDSTextureLoader.cpp @@ -0,0 +1,787 @@ +//-------------------------------------------------------------------------------------- +// File: XboxDDSTextureLoader.cpp +// +// Functions for loading a DDS texture using the XBOX extended header and creating a +// Direct3D11.X runtime resource for it via the CreatePlacement APIs +// +// Note these functions will not load standard DDS files. Use the DDSTextureLoader +// module in the DirectXTex package or as part of the DirectXTK library to load +// these files which use standard Direct3D resource creation APIs. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "XboxDDSTextureLoader.h" + +#include "dds.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" + +#include + +using namespace DirectX; +using namespace Xbox; + +namespace +{ + //-------------------------------------------------------------------------------------- + // DDS file structure definitions + // + // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library + //-------------------------------------------------------------------------------------- + #pragma pack(push,1) + + struct DDS_HEADER_XBOX + // Must match structure defined in xtexconv tool + { + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 + uint32_t tileMode; // see XG_TILE_MODE + uint32_t baseAlignment; + uint32_t dataSize; + uint32_t xdkVer; // matching _XDK_VER + }; + + static_assert(sizeof(DDS_HEADER_XBOX) == 36, "DDS XBOX Header size mismatch"); + + #pragma pack(pop) + + //-------------------------------------------------------------------------------------- + HRESULT LoadTextureDataFromFile(_In_z_ const wchar_t* fileName, + std::unique_ptr& ddsData, + DDS_HEADER** header, + uint8_t** bitData, + size_t* bitSize + ) + { + if (!header || !bitData || !bitSize) + { + return E_POINTER; + } + + // open the file + ScopedHandle hFile(safe_handle(CreateFile2(fileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr))); + + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + LARGE_INTEGER FileSize = { 0 }; + + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + FileSize = fileInfo.EndOfFile; + + // File is too big for 32-bit allocation, so reject read + if (FileSize.HighPart > 0) + { + return E_FAIL; + } + + // Need at least enough data to fill the header and magic number to be a valid DDS + if (FileSize.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // create enough space for the file data + ddsData.reset(new (std::nothrow) uint8_t[FileSize.LowPart]); + if (!ddsData) + { + return E_OUTOFMEMORY; + } + + // read the data in + DWORD BytesRead = 0; + if (!ReadFile(hFile.get(), + ddsData.get(), + FileSize.LowPart, + &BytesRead, + nullptr + )) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (BytesRead < FileSize.LowPart) + { + return E_FAIL; + } + + // DDS files always start with the same magic number ("DDS ") + uint32_t dwMagicNumber = *(const uint32_t*)(ddsData.get()); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto hdr = reinterpret_cast(ddsData.get() + sizeof(uint32_t)); + + // Verify header to validate DDS file + if (hdr->size != sizeof(DDS_HEADER) || + hdr->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for XBOX extension + if (!(hdr->ddspf.flags & DDS_FOURCC) + || (MAKEFOURCC('X', 'B', 'O', 'X') != hdr->ddspf.fourCC)) + { + // Use standard DDSTextureLoader instead + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Must be long enough for both headers and magic value + if (FileSize.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_XBOX))) + { + return E_FAIL; + } + + // setup the pointers in the process request + *header = hdr; + ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_XBOX); + *bitData = ddsData.get() + offset; + *bitSize = FileSize.LowPart - offset; + + return S_OK; + } + + //-------------------------------------------------------------------------------------- + DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; + } + } + + //-------------------------------------------------------------------------------------- + HRESULT CreateD3DResources(_In_ ID3D11DeviceX* d3dDevice, + _In_ const DDS_HEADER_XBOX* xboxext, + _In_ uint32_t width, + _In_ uint32_t height, + _In_ uint32_t depth, + _In_ uint32_t mipCount, + _In_ uint32_t arraySize, + _In_ bool forceSRGB, + _In_ bool isCubeMap, + _In_ void* grfxMemory, + _Outptr_opt_ ID3D11Resource** texture, + _Outptr_opt_ ID3D11ShaderResourceView** textureView) + { + if (!d3dDevice || !grfxMemory) + return E_POINTER; + + HRESULT hr = E_FAIL; + + DXGI_FORMAT format = xboxext->dxgiFormat; + if (forceSRGB) + { + format = MakeSRGB(format); + } + + switch (xboxext->resourceDimension) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + { + D3D11_TEXTURE1D_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.Width = static_cast(width); + desc.MipLevels = static_cast(mipCount); + desc.ArraySize = static_cast(arraySize); + desc.Format = format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ID3D11Texture1D* tex = nullptr; + hr = d3dDevice->CreatePlacementTexture1D(&desc, xboxext->tileMode, 0, grfxMemory, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + if (textureView != 0) + { + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset(&SRVDesc, 0, sizeof(SRVDesc)); + SRVDesc.Format = format; + + if (arraySize > 1) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + SRVDesc.Texture1DArray.MipLevels = desc.MipLevels; + SRVDesc.Texture1DArray.ArraySize = static_cast(arraySize); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MipLevels = desc.MipLevels; + } + + hr = d3dDevice->CreateShaderResourceView(tex, + &SRVDesc, + textureView + ); + if (FAILED(hr)) + { + tex->Release(); + return hr; + } + } + + if (texture != 0) + { + *texture = tex; + } + else + { + SetDebugObjectName(tex, "XboxDDSTextureLoader"); + tex->Release(); + } + } + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + { + D3D11_TEXTURE2D_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.Width = static_cast(width); + desc.Height = static_cast(height); + desc.MipLevels = static_cast(mipCount); + desc.ArraySize = static_cast(arraySize); + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.MiscFlags = (isCubeMap) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; + + ID3D11Texture2D* tex = nullptr; + hr = d3dDevice->CreatePlacementTexture2D(&desc, xboxext->tileMode, 0, grfxMemory, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + if (textureView != 0) + { + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset(&SRVDesc, 0, sizeof(SRVDesc)); + SRVDesc.Format = format; + + if (isCubeMap) + { + if (arraySize > 6) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; + SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels; + + // Earlier we set arraySize to (NumCubes * 6) + SRVDesc.TextureCubeArray.NumCubes = static_cast(arraySize / 6); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MipLevels = desc.MipLevels; + } + } + else if (arraySize > 1) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + SRVDesc.Texture2DArray.MipLevels = desc.MipLevels; + SRVDesc.Texture2DArray.ArraySize = static_cast(arraySize); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = desc.MipLevels; + } + + hr = d3dDevice->CreateShaderResourceView(tex, + &SRVDesc, + textureView + ); + if (FAILED(hr)) + { + tex->Release(); + return hr; + } + } + + if (texture != 0) + { + *texture = tex; + } + else + { + SetDebugObjectName(tex, "XboxDDSTextureLoader"); + tex->Release(); + } + } + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + { + D3D11_TEXTURE3D_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.Width = static_cast(width); + desc.Height = static_cast(height); + desc.Depth = static_cast(depth); + desc.MipLevels = static_cast(mipCount); + desc.Format = format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ID3D11Texture3D* tex = nullptr; + hr = d3dDevice->CreatePlacementTexture3D(&desc, xboxext->tileMode, 0, grfxMemory, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + if (textureView != 0) + { + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset(&SRVDesc, 0, sizeof(SRVDesc)); + SRVDesc.Format = format; + + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MipLevels = desc.MipLevels; + + hr = d3dDevice->CreateShaderResourceView(tex, + &SRVDesc, + textureView + ); + if (FAILED(hr)) + { + tex->Release(); + return hr; + } + } + + if (texture != 0) + { + *texture = tex; + } + else + { + SetDebugObjectName(tex, "XboxDDSTextureLoader"); + tex->Release(); + } + } + } + break; + } + + return hr; + } + + //-------------------------------------------------------------------------------------- + HRESULT CreateTextureFromDDS(_In_ ID3D11DeviceX* d3dDevice, + _In_ const DDS_HEADER* header, + _In_reads_bytes_(bitSize) const uint8_t* bitData, + _In_ size_t bitSize, + _In_ bool forceSRGB, + _Outptr_opt_ ID3D11Resource** texture, + _Outptr_opt_ ID3D11ShaderResourceView** textureView, + _Outptr_ void** grfxMemory) + { + HRESULT hr = S_OK; + + uint32_t width = header->width; + uint32_t height = header->height; + uint32_t depth = header->depth; + + uint32_t mipCount = header->mipMapCount; + if (0 == mipCount) + { + mipCount = 1; + } + + if (!(header->ddspf.flags & DDS_FOURCC) + || (MAKEFOURCC('X', 'B', 'O', 'X') != header->ddspf.fourCC)) + { + // Use standard DDSTextureLoader instead + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + +#ifndef NDEBUG + if (xboxext->xdkVer < _XDK_VER) + { + OutputDebugStringA("WARNING: DDS XBOX file may be outdated and need regeneration\n"); + } +#endif + + uint32_t arraySize = xboxext->arraySize; + if (arraySize == 0) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + bool isCubeMap = false; + + switch (xboxext->resourceDimension) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + if ((header->flags & DDS_HEIGHT) && height != 1) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + height = depth = 1; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + if (xboxext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE) + { + arraySize *= 6; + isCubeMap = true; + } + depth = 1; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + if (!(header->flags & DDS_HEADER_FLAGS_VOLUME)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + if (arraySize > 1) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Bound sizes + if (mipCount > D3D11_REQ_MIP_LEVELS) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + switch (xboxext->resourceDimension) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURE1D_U_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + if (isCubeMap) + { + // This is the right bound because we set arraySize to (NumCubes*6) above + if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURECUBE_DIMENSION) || + (height > D3D11_REQ_TEXTURECUBE_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) || + (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + if ((arraySize > 1) || + (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + } + + if (xboxext->dxgiFormat == DXGI_FORMAT_UNKNOWN) + { + return E_FAIL; + } + + if (!xboxext->dataSize || !xboxext->baseAlignment) + { + return E_FAIL; + } + + if (xboxext->dataSize > bitSize) + { + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } + + // Allocate graphics memory + size_t sizeBytes = (size_t(xboxext->dataSize) + 0xFFF) & ~0xFFF; // 4K boundary + size_t alignmentBytes = std::max(xboxext->baseAlignment, 4096); + + hr = D3DAllocateGraphicsMemory(sizeBytes, alignmentBytes, 0, D3D11_GRAPHICS_MEMORY_ACCESS_CPU_CACHE_COHERENT, grfxMemory); + if (FAILED(hr)) + return hr; + + assert(*grfxMemory != 0); + + // Copy tiled data into graphics memory + memcpy(*grfxMemory, bitData, xboxext->dataSize); + + // Create the texture + hr = CreateD3DResources(d3dDevice, xboxext, + width, height, depth, mipCount, arraySize, + forceSRGB, isCubeMap, *grfxMemory, + texture, textureView); + if (FAILED(hr)) + { + (void)D3DFreeGraphicsMemory(*grfxMemory); + *grfxMemory = nullptr; + } + + return hr; + } + + //-------------------------------------------------------------------------------------- + DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) + { + if (header->ddspf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('X', 'B', 'O', 'X') == header->ddspf.fourCC) + { + auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + auto mode = static_cast(xboxext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK); + switch (mode) + { + case DDS_ALPHA_MODE_STRAIGHT: + case DDS_ALPHA_MODE_PREMULTIPLIED: + case DDS_ALPHA_MODE_OPAQUE: + case DDS_ALPHA_MODE_CUSTOM: + return mode; + + default: + break; + } + } + } + + return DDS_ALPHA_MODE_UNKNOWN; + } +} // anonymous namespace + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateDDSTextureFromMemory( ID3D11DeviceX* d3dDevice, + const uint8_t* ddsData, + size_t ddsDataSize, + ID3D11Resource** texture, + ID3D11ShaderResourceView** textureView, + void** grfxMemory, + DDS_ALPHA_MODE* alphaMode, + bool forceSRGB ) +{ + if ( texture ) + { + *texture = nullptr; + } + if ( textureView ) + { + *textureView = nullptr; + } + if ( grfxMemory ) + { + *grfxMemory = nullptr; + } + if ( alphaMode ) + { + *alphaMode = DDS_ALPHA_MODE_UNKNOWN; + } + + if ( !d3dDevice || !ddsData || (!texture && !textureView) || !grfxMemory ) + { + return E_INVALIDARG; + } + + // Validate DDS file in memory + if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + { + return E_FAIL; + } + + uint32_t dwMagicNumber = *( const uint32_t* )( ddsData ); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto header = reinterpret_cast( ddsData + sizeof( uint32_t ) ); + + // Verify header to validate DDS file + if (header->size != sizeof(DDS_HEADER) || + header->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for XBOX extension + if ( !( header->ddspf.flags & DDS_FOURCC ) + || ( MAKEFOURCC( 'X', 'B', 'O', 'X' ) != header->ddspf.fourCC ) ) + { + // Use standard DDSTextureLoader instead + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + // Must be long enough for both headers and magic value + if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_XBOX))) + { + return E_FAIL; + } + + ptrdiff_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER ) + sizeof( DDS_HEADER_XBOX ); + + HRESULT hr = CreateTextureFromDDS( d3dDevice, header, + ddsData + offset, ddsDataSize - offset, forceSRGB, + texture, textureView, + grfxMemory ); + if ( SUCCEEDED(hr) ) + { + if (texture != 0 && *texture != 0) + { + SetDebugObjectName(*texture, "XboxDDSTextureLoader"); + } + + if (textureView != 0 && *textureView != 0) + { + SetDebugObjectName(*textureView, "XboxDDSTextureLoader"); + } + + if ( alphaMode ) + *alphaMode = GetAlphaMode( header ); + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateDDSTextureFromFile( ID3D11DeviceX* d3dDevice, + const wchar_t* fileName, + ID3D11Resource** texture, + ID3D11ShaderResourceView** textureView, + void** grfxMemory, + DDS_ALPHA_MODE* alphaMode, + bool forceSRGB ) +{ + if ( texture ) + { + *texture = nullptr; + } + if ( textureView ) + { + *textureView = nullptr; + } + if ( grfxMemory ) + { + *grfxMemory = nullptr; + } + if ( alphaMode ) + { + *alphaMode = DDS_ALPHA_MODE_UNKNOWN; + } + + if ( !d3dDevice || !fileName || (!texture && !textureView) || !grfxMemory ) + { + return E_INVALIDARG; + } + + DDS_HEADER* header = nullptr; + uint8_t* bitData = nullptr; + size_t bitSize = 0; + + std::unique_ptr ddsData; + HRESULT hr = LoadTextureDataFromFile( fileName, + ddsData, + &header, + &bitData, + &bitSize + ); + if (FAILED(hr)) + { + return hr; + } + + hr = CreateTextureFromDDS( d3dDevice, header, + bitData, bitSize, forceSRGB, + texture, textureView, + grfxMemory ); + + if ( SUCCEEDED(hr) ) + { +#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + if (texture != 0 && *texture != 0) + { + (*texture)->SetName( fileName ); + } + if (textureView != 0 && *textureView != 0 ) + { + (*textureView)->SetName( fileName ); + } +#endif + + if ( alphaMode ) + *alphaMode = GetAlphaMode( header ); + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void Xbox::FreeDDSTextureMemory(void* grfxMemory) +{ + if (grfxMemory) + { + (void)D3DFreeGraphicsMemory(grfxMemory); + } +} diff --git a/Kits/DirectXTK12/DirectXTK_XboxOneXDK_2015.vcxproj b/Kits/DirectXTK12/DirectXTK_XboxOneXDK_2015.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..9e7867cd0e93f01119c77eb1643d3995d9b10523 --- /dev/null +++ b/Kits/DirectXTK12/DirectXTK_XboxOneXDK_2015.vcxproj @@ -0,0 +1,568 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + + + + + + Document + + + + + Document + + + + + Document + + + + + Document + + + + DirectXTK12 + DirectXTK12 + {0EE6C863-556C-4815-8BFF-A5A0B25A948F} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + StaticLibrary + v140 + false + Unicode + false + false + + + StaticLibrary + v140 + false + Unicode + false + false + + + StaticLibrary + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + DirectXTK12 + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + DirectXTK12 + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + Bin\XboxOneXDK_2015\$(Platform)\$(Configuration)\ + DirectXTK12 + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib; + + + true + Windows + true + true + false + + + Use + pch.h + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;_LIB;%(PreprocessorDefinitions) + EnableAllWarnings + true + true + false + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib; + + + true + Windows + true + true + false + + + Use + pch.h + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;_LIB;PROFILE;%(PreprocessorDefinitions) + EnableAllWarnings + true + true + false + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib; + Windows + true + false + + + pch.h + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + EnableAllWarnings + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;_LIB;%(PreprocessorDefinitions) + false + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTK12/DirectXTK_XboxOneXDK_2015.vcxproj.filters b/Kits/DirectXTK12/DirectXTK_XboxOneXDK_2015.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..5224b503eb082ca98394e92c174926462a02c19d --- /dev/null +++ b/Kits/DirectXTK12/DirectXTK_XboxOneXDK_2015.vcxproj.filters @@ -0,0 +1,1099 @@ + + + + + {37d8d298-8ff7-4b16-9de2-1e8e5b943795} + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {c063e2fe-d3cf-4663-a7f4-efab29334219} + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {1d7c612f-bf24-4368-a247-46d28920c4a7} + + + {5bfd0d52-ee7d-4cf1-aab2-235c7a1f9d6e} + + + {302026c2-811a-448d-b7c5-67fc7c84c157} + + + {3c422910-8708-452c-81b7-9e692884dca8} + + + {cc2a3749-62ef-4b80-9da0-3b25decbc88d} + + + + + Audio + + + Audio + + + Audio + + + Audio + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Src + + + Src + + + Inc + + + Inc + + + Inc + + + Src + + + Src + + + Inc\Shared + + + Inc\Shared + + + Inc\Shared + + + Inc\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Inc + + + Inc + + + Inc + + + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Inc\Shared + + + Src\Shared + + + Src\Shaders\Shared + + + Src\Shaders\Shared + + + Src\Shaders + + + Src\Shaders\Shared + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders + + + Src\Shaders\Shared + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + Src\Shaders\Symbols + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTK12/Inc/XboxDDSTextureLoader.h b/Kits/DirectXTK12/Inc/XboxDDSTextureLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..23a18a159152139d53c8d7789ab98bebb47fff58 --- /dev/null +++ b/Kits/DirectXTK12/Inc/XboxDDSTextureLoader.h @@ -0,0 +1,84 @@ +//-------------------------------------------------------------------------------------- +// File: XboxDDSTextureLoader.h +// +// Functions for loading a DDS texture using the XBOX extended header and creating a +// Direct3D12.X runtime resource for it via the CreatePlacedResourceX API +// +// Note these functions will not load standard DDS files. Use the DDSTextureLoader +// module in the DirectXTex package or as part of the DirectXTK library to load +// these files which use standard Direct3D resource creation APIs. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#error This module only supports Xbox One exclusive apps +#endif + +#include + +#include + +namespace Xbox +{ + enum DDS_ALPHA_MODE + { + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, + }; + + // + // NOTE: Flush the GPU caches before using textures created + // with these functions. + // + // The simplest means of doing this is: + // + // // Load all your textures: + // CreateDDSTextureFrom... + // CreateDDSTextureFrom... + // CreateDDSTextureFrom... + // + // // Flush the GPU caches + // ID3D12CommandList::FlushPipelineX(D3D12XBOX_FLUSH_IDLE, 0, 0); + // + // // Now it's safe to use the textures + // ... Draw ... + // + // You may wish to consider more fine-grained flushes if + // creating textures at run-time. See the documentation for + // FlushPipelineX. + // + + HRESULT __cdecl CreateDDSTextureFromMemory( + _In_ ID3D12Device* d3dDevice, + _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, + _In_ size_t ddsDataSize, + _Outptr_opt_ ID3D12Resource** texture, + _Outptr_ void** grfxMemory, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _In_ bool forceSRGB = false, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl CreateDDSTextureFromFile( + _In_ ID3D12Device* d3dDevice, + _In_z_ const wchar_t* szFileName, + _Outptr_opt_ ID3D12Resource** texture, + _Outptr_ void** grfxMemory, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _In_ bool forceSRGB = false, + _Out_opt_ bool* isCubeMap = nullptr); + + void FreeDDSTextureMemory(_In_opt_ void* grfxMemory); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/XboxDDSTextureLoader.cpp b/Kits/DirectXTK12/Src/XboxDDSTextureLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b36be2d529156eac5c03946a62359f71d91f557 --- /dev/null +++ b/Kits/DirectXTK12/Src/XboxDDSTextureLoader.cpp @@ -0,0 +1,625 @@ +//-------------------------------------------------------------------------------------- +// File: XboxDDSTextureLoader.cpp +// +// Functions for loading a DDS texture using the XBOX extended header and creating a +// Direct3D12.X runtime resource for it via the CreatePlacedResourceX API +// +// Note these functions will not load standard DDS files. Use the DDSTextureLoader +// module in the DirectXTex package or as part of the DirectXTK library to load +// these files which use standard Direct3D resource creation APIs. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "XboxDDSTextureLoader.h" + +#include "dds.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" + +#include + +using namespace DirectX; +using namespace Xbox; + +namespace +{ + //-------------------------------------------------------------------------------------- + // Default XMemAlloc attributes for texture loading + //-------------------------------------------------------------------------------------- + const uint64_t c_XMemAllocAttributes = MAKE_XALLOC_ATTRIBUTES( + eXALLOCAllocatorId_MiddlewareReservedMin, + 0, + XALLOC_MEMTYPE_GRAPHICS_WRITECOMBINE_GPU_READONLY, + XALLOC_PAGESIZE_64KB, + XALLOC_ALIGNMENT_64K); + + //-------------------------------------------------------------------------------------- + // DDS file structure definitions + // + // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library + //-------------------------------------------------------------------------------------- + #pragma pack(push,1) + + struct DDS_HEADER_XBOX + // Must match structure defined in xtexconv tool + { + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 + uint32_t tileMode; // see XG_TILE_MODE + uint32_t baseAlignment; + uint32_t dataSize; + uint32_t xdkVer; // matching _XDK_VER + }; + + static_assert(sizeof(DDS_HEADER_XBOX) == 36, "DDS XBOX Header size mismatch"); + + #pragma pack(pop) + + //-------------------------------------------------------------------------------------- + HRESULT LoadTextureDataFromFile(_In_z_ const wchar_t* fileName, + std::unique_ptr& ddsData, + DDS_HEADER** header, + uint8_t** bitData, + size_t* bitSize + ) + { + if (!header || !bitData || !bitSize) + { + return E_POINTER; + } + + // open the file + ScopedHandle hFile(safe_handle(CreateFile2(fileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr))); + + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read + if (fileInfo.EndOfFile.HighPart > 0) + { + return E_FAIL; + } + + // Need at least enough data to fill the header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // create enough space for the file data + ddsData.reset(new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart]); + if (!ddsData) + { + return E_OUTOFMEMORY; + } + + // read the data in + DWORD BytesRead = 0; + if (!ReadFile(hFile.get(), + ddsData.get(), + fileInfo.EndOfFile.LowPart, + &BytesRead, + nullptr + )) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (BytesRead < fileInfo.EndOfFile.LowPart) + { + return E_FAIL; + } + + // DDS files always start with the same magic number ("DDS ") + uint32_t dwMagicNumber = *(const uint32_t*)(ddsData.get()); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto hdr = reinterpret_cast(ddsData.get() + sizeof(uint32_t)); + + // Verify header to validate DDS file + if (hdr->size != sizeof(DDS_HEADER) || + hdr->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for XBOX extension + if (!(hdr->ddspf.flags & DDS_FOURCC) + || (MAKEFOURCC('X', 'B', 'O', 'X') != hdr->ddspf.fourCC)) + { + // Use standard DDSTextureLoader instead + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Must be long enough for both headers and magic value + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_XBOX))) + { + return E_FAIL; + } + + // setup the pointers in the process request + *header = hdr; + ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_XBOX); + *bitData = ddsData.get() + offset; + *bitSize = fileInfo.EndOfFile.LowPart - offset; + + return S_OK; + } + + //-------------------------------------------------------------------------------------- + DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; + } + } + + //-------------------------------------------------------------------------------------- + HRESULT CreateD3DResources(_In_ ID3D12Device* d3dDevice, + _In_ const DDS_HEADER_XBOX* xboxext, + _In_ uint32_t width, + _In_ uint32_t height, + _In_ uint32_t depth, + _In_ uint32_t mipCount, + _In_ uint32_t arraySize, + _In_ bool forceSRGB, + _In_ void* grfxMemory, + _Outptr_ ID3D12Resource** texture) + { + if (!d3dDevice || !grfxMemory) + return E_POINTER; + + HRESULT hr = E_FAIL; + + DXGI_FORMAT format = xboxext->dxgiFormat; + if (forceSRGB) + { + format = MakeSRGB(format); + } + + D3D12_RESOURCE_DESC desc = {}; + desc.Width = static_cast(width); + desc.Height = static_cast(height); + desc.MipLevels = static_cast(mipCount); + desc.DepthOrArraySize = (xboxext->resourceDimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) ? static_cast(depth) : static_cast(arraySize); + desc.Format = format; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Dimension = static_cast(xboxext->resourceDimension); + desc.Layout = static_cast(0x100 | xboxext->tileMode); + + hr = d3dDevice->CreatePlacedResourceX( + reinterpret_cast(grfxMemory), + &desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + nullptr, + IID_GRAPHICS_PPV_ARGS(texture)); + if (SUCCEEDED(hr)) + { + _Analysis_assume_(*texture != nullptr); + SetDebugObjectName(*texture, L"XboxDDSTextureLoader"); + } + + return hr; + } + + //-------------------------------------------------------------------------------------- + HRESULT CreateTextureFromDDS(_In_ ID3D12Device* d3dDevice, + _In_ const DDS_HEADER* header, + _In_reads_bytes_(bitSize) const uint8_t* bitData, + _In_ size_t bitSize, + _In_ bool forceSRGB, + _Outptr_ ID3D12Resource** texture, + _Outptr_ void** grfxMemory, + _Out_opt_ bool* outIsCubeMap) + { + HRESULT hr = S_OK; + + uint32_t width = header->width; + uint32_t height = header->height; + uint32_t depth = header->depth; + + uint32_t mipCount = header->mipMapCount; + if (0 == mipCount) + { + mipCount = 1; + } + + if (!(header->ddspf.flags & DDS_FOURCC) + || (MAKEFOURCC('X', 'B', 'O', 'X') != header->ddspf.fourCC)) + { + // Use standard DDSTextureLoader instead + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + +#ifndef NDEBUG + if (xboxext->xdkVer < _XDK_VER) + { + OutputDebugStringA("WARNING: DDS XBOX file may be outdated and need regeneration\n"); + } +#endif + + uint32_t arraySize = xboxext->arraySize; + if (arraySize == 0) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + bool isCubeMap = false; + + switch (xboxext->resourceDimension) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + if ((header->flags & DDS_HEIGHT) && height != 1) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + height = depth = 1; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + if (xboxext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE) + { + arraySize *= 6; + isCubeMap = true; + } + depth = 1; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + if (!(header->flags & DDS_HEADER_FLAGS_VOLUME)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + if (arraySize > 1) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Bound sizes + if (mipCount > D3D11_REQ_MIP_LEVELS) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + switch (xboxext->resourceDimension) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURE1D_U_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + if (isCubeMap) + { + // This is the right bound because we set arraySize to (NumCubes*6) above + if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURECUBE_DIMENSION) || + (height > D3D11_REQ_TEXTURECUBE_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) || + (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + if ((arraySize > 1) || + (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + } + + if (xboxext->dxgiFormat == DXGI_FORMAT_UNKNOWN) + { + return E_FAIL; + } + + if (!xboxext->dataSize || !xboxext->baseAlignment) + { + return E_FAIL; + } + + if (xboxext->dataSize > bitSize) + { + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } + + // Allocate graphics memory. Depending on the data size it uses 4MB or 64K pages. + *grfxMemory = XMemAlloc(xboxext->dataSize, c_XMemAllocAttributes); + if (!*grfxMemory) + return E_OUTOFMEMORY; + + // Copy tiled data into graphics memory + memcpy(*grfxMemory, bitData, xboxext->dataSize); + + // Create the texture + hr = CreateD3DResources(d3dDevice, xboxext, + width, height, depth, mipCount, arraySize, + forceSRGB, *grfxMemory, + texture); + if (FAILED(hr)) + { + XMemFree(*grfxMemory, c_XMemAllocAttributes); + *grfxMemory = nullptr; + } + + if (outIsCubeMap) + { + *outIsCubeMap = isCubeMap; + } + + return hr; + } + + //-------------------------------------------------------------------------------------- + DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) + { + if (header->ddspf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('X', 'B', 'O', 'X') == header->ddspf.fourCC) + { + auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + auto mode = static_cast(xboxext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK); + switch (mode) + { + case DDS_ALPHA_MODE_STRAIGHT: + case DDS_ALPHA_MODE_PREMULTIPLIED: + case DDS_ALPHA_MODE_OPAQUE: + case DDS_ALPHA_MODE_CUSTOM: + return mode; + + default: + break; + } + } + } + + return DDS_ALPHA_MODE_UNKNOWN; + } +} // anonymous namespace + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateDDSTextureFromMemory( + ID3D12Device* d3dDevice, + const uint8_t* ddsData, + size_t ddsDataSize, + ID3D12Resource** texture, + void** grfxMemory, + DDS_ALPHA_MODE* alphaMode, + bool forceSRGB, + bool* isCubeMap ) +{ + if (texture) + { + *texture = nullptr; + } + + if (grfxMemory) + { + *grfxMemory = nullptr; + } + + if (alphaMode) + { + *alphaMode = DDS_ALPHA_MODE_UNKNOWN; + } + + if (isCubeMap) + { + *isCubeMap = false; + } + + if ( !d3dDevice || !ddsData || !texture || !grfxMemory ) + { + return E_INVALIDARG; + } + + // Validate DDS file in memory + if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + { + return E_FAIL; + } + + uint32_t dwMagicNumber = *( const uint32_t* )( ddsData ); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto header = reinterpret_cast( ddsData + sizeof( uint32_t ) ); + + // Verify header to validate DDS file + if (header->size != sizeof(DDS_HEADER) || + header->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for XBOX extension + if ( !( header->ddspf.flags & DDS_FOURCC ) + || ( MAKEFOURCC( 'X', 'B', 'O', 'X' ) != header->ddspf.fourCC ) ) + { + // Use standard DDSTextureLoader instead + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + // Must be long enough for both headers and magic value + if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_XBOX))) + { + return E_FAIL; + } + + ptrdiff_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER ) + sizeof( DDS_HEADER_XBOX ); + + HRESULT hr = CreateTextureFromDDS( d3dDevice, header, + ddsData + offset, ddsDataSize - offset, forceSRGB, + texture, grfxMemory, isCubeMap ); + if ( SUCCEEDED(hr) ) + { + _Analysis_assume_(*texture != nullptr); + SetDebugObjectName(*texture, L"XboxDDSTextureLoader"); + + if ( alphaMode ) + *alphaMode = GetAlphaMode( header ); + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateDDSTextureFromFile( + ID3D12Device* d3dDevice, + const wchar_t* fileName, + ID3D12Resource** texture, + void** grfxMemory, + DDS_ALPHA_MODE* alphaMode, + bool forceSRGB, + bool* isCubeMap ) +{ + if (texture) + { + *texture = nullptr; + } + + if (grfxMemory) + { + *grfxMemory = nullptr; + } + + if (alphaMode) + { + *alphaMode = DDS_ALPHA_MODE_UNKNOWN; + } + + if (isCubeMap) + { + *isCubeMap = false; + } + + if ( !d3dDevice || !fileName || !texture || !grfxMemory ) + { + return E_INVALIDARG; + } + + DDS_HEADER* header = nullptr; + uint8_t* bitData = nullptr; + size_t bitSize = 0; + + std::unique_ptr ddsData; + HRESULT hr = LoadTextureDataFromFile( fileName, + ddsData, + &header, + &bitData, + &bitSize + ); + if (FAILED(hr)) + { + return hr; + } + + hr = CreateTextureFromDDS( d3dDevice, header, + bitData, bitSize, forceSRGB, + texture, grfxMemory, isCubeMap ); + + if ( SUCCEEDED(hr) ) + { +#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + if (texture != nullptr && *texture != nullptr) + { + (*texture)->SetName( fileName ); + } +#endif + + if ( alphaMode ) + *alphaMode = GetAlphaMode( header ); + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void Xbox::FreeDDSTextureMemory(void* grfxMemory) +{ + if (grfxMemory) + { + XMemFree(grfxMemory, c_XMemAllocAttributes); + } +} diff --git a/Kits/DirectXTex/BC.cpp b/Kits/DirectXTex/BC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a342f2a511fb47d6e1f7988d5f87c0453c8945cc --- /dev/null +++ b/Kits/DirectXTex/BC.cpp @@ -0,0 +1,1148 @@ +//------------------------------------------------------------------------------------- +// BC.cpp +// +// Block-compression (BC) functionality for BC1, BC2, BC3 (orginal DXTn formats) +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +// Experiemental encoding variants, not enabled by default +//#define COLOR_WEIGHTS +//#define COLOR_AVG_0WEIGHTS + +#include "BC.h" + +using namespace DirectX; +using namespace DirectX::PackedVector; + +namespace +{ + //------------------------------------------------------------------------------------- + // Constants + //------------------------------------------------------------------------------------- + + // Perceptual weightings for the importance of each channel. + const HDRColorA g_Luminance(0.2125f / 0.7154f, 1.0f, 0.0721f / 0.7154f, 1.0f); + const HDRColorA g_LuminanceInv(0.7154f / 0.2125f, 1.0f, 0.7154f / 0.0721f, 1.0f); + + //------------------------------------------------------------------------------------- + // Decode/Encode RGB 5/6/5 colors + //------------------------------------------------------------------------------------- + inline void Decode565(_Out_ HDRColorA *pColor, _In_ const uint16_t w565) + { + pColor->r = (float)((w565 >> 11) & 31) * (1.0f / 31.0f); + pColor->g = (float)((w565 >> 5) & 63) * (1.0f / 63.0f); + pColor->b = (float)((w565 >> 0) & 31) * (1.0f / 31.0f); + pColor->a = 1.0f; + } + + inline uint16_t Encode565(_In_ const HDRColorA *pColor) + { + HDRColorA Color; + + Color.r = (pColor->r < 0.0f) ? 0.0f : (pColor->r > 1.0f) ? 1.0f : pColor->r; + Color.g = (pColor->g < 0.0f) ? 0.0f : (pColor->g > 1.0f) ? 1.0f : pColor->g; + Color.b = (pColor->b < 0.0f) ? 0.0f : (pColor->b > 1.0f) ? 1.0f : pColor->b; + + uint16_t w; + + w = (uint16_t)((static_cast(Color.r * 31.0f + 0.5f) << 11) | + (static_cast(Color.g * 63.0f + 0.5f) << 5) | + (static_cast(Color.b * 31.0f + 0.5f) << 0)); + + return w; + } + + + //------------------------------------------------------------------------------------- + void OptimizeRGB( + _Out_ HDRColorA *pX, + _Out_ HDRColorA *pY, + _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pPoints, + size_t cSteps, + DWORD flags) + { + static const float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f); + static const float pC3[] = { 2.0f / 2.0f, 1.0f / 2.0f, 0.0f / 2.0f }; + static const float pD3[] = { 0.0f / 2.0f, 1.0f / 2.0f, 2.0f / 2.0f }; + static const float pC4[] = { 3.0f / 3.0f, 2.0f / 3.0f, 1.0f / 3.0f, 0.0f / 3.0f }; + static const float pD4[] = { 0.0f / 3.0f, 1.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f }; + + const float *pC = (3 == cSteps) ? pC3 : pC4; + const float *pD = (3 == cSteps) ? pD3 : pD4; + + // Find Min and Max points, as starting point + HDRColorA X = (flags & BC_FLAGS_UNIFORM) ? HDRColorA(1.f, 1.f, 1.f, 1.f) : g_Luminance; + HDRColorA Y = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); + + for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++) + { +#ifdef COLOR_WEIGHTS + if (pPoints[iPoint].a > 0.0f) +#endif // COLOR_WEIGHTS + { + if (pPoints[iPoint].r < X.r) + X.r = pPoints[iPoint].r; + + if (pPoints[iPoint].g < X.g) + X.g = pPoints[iPoint].g; + + if (pPoints[iPoint].b < X.b) + X.b = pPoints[iPoint].b; + + if (pPoints[iPoint].r > Y.r) + Y.r = pPoints[iPoint].r; + + if (pPoints[iPoint].g > Y.g) + Y.g = pPoints[iPoint].g; + + if (pPoints[iPoint].b > Y.b) + Y.b = pPoints[iPoint].b; + } + } + + // Diagonal axis + HDRColorA AB; + + AB.r = Y.r - X.r; + AB.g = Y.g - X.g; + AB.b = Y.b - X.b; + + float fAB = AB.r * AB.r + AB.g * AB.g + AB.b * AB.b; + + // Single color block.. no need to root-find + if (fAB < FLT_MIN) + { + pX->r = X.r; pX->g = X.g; pX->b = X.b; + pY->r = Y.r; pY->g = Y.g; pY->b = Y.b; + return; + } + + // Try all four axis directions, to determine which diagonal best fits data + float fABInv = 1.0f / fAB; + + HDRColorA Dir; + Dir.r = AB.r * fABInv; + Dir.g = AB.g * fABInv; + Dir.b = AB.b * fABInv; + + HDRColorA Mid; + Mid.r = (X.r + Y.r) * 0.5f; + Mid.g = (X.g + Y.g) * 0.5f; + Mid.b = (X.b + Y.b) * 0.5f; + + float fDir[4]; + fDir[0] = fDir[1] = fDir[2] = fDir[3] = 0.0f; + + + for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++) + { + HDRColorA Pt; + Pt.r = (pPoints[iPoint].r - Mid.r) * Dir.r; + Pt.g = (pPoints[iPoint].g - Mid.g) * Dir.g; + Pt.b = (pPoints[iPoint].b - Mid.b) * Dir.b; + + float f; + +#ifdef COLOR_WEIGHTS + f = Pt.r + Pt.g + Pt.b; + fDir[0] += pPoints[iPoint].a * f * f; + + f = Pt.r + Pt.g - Pt.b; + fDir[1] += pPoints[iPoint].a * f * f; + + f = Pt.r - Pt.g + Pt.b; + fDir[2] += pPoints[iPoint].a * f * f; + + f = Pt.r - Pt.g - Pt.b; + fDir[3] += pPoints[iPoint].a * f * f; +#else + f = Pt.r + Pt.g + Pt.b; + fDir[0] += f * f; + + f = Pt.r + Pt.g - Pt.b; + fDir[1] += f * f; + + f = Pt.r - Pt.g + Pt.b; + fDir[2] += f * f; + + f = Pt.r - Pt.g - Pt.b; + fDir[3] += f * f; +#endif // COLOR_WEIGHTS + } + + float fDirMax = fDir[0]; + size_t iDirMax = 0; + + for (size_t iDir = 1; iDir < 4; iDir++) + { + if (fDir[iDir] > fDirMax) + { + fDirMax = fDir[iDir]; + iDirMax = iDir; + } + } + + if (iDirMax & 2) + { + float f = X.g; X.g = Y.g; Y.g = f; + } + + if (iDirMax & 1) + { + float f = X.b; X.b = Y.b; Y.b = f; + } + + + // Two color block.. no need to root-find + if (fAB < 1.0f / 4096.0f) + { + pX->r = X.r; pX->g = X.g; pX->b = X.b; + pY->r = Y.r; pY->g = Y.g; pY->b = Y.b; + return; + } + + // Use Newton's Method to find local minima of sum-of-squares error. + float fSteps = (float)(cSteps - 1); + + for (size_t iIteration = 0; iIteration < 8; iIteration++) + { + // Calculate new steps + HDRColorA pSteps[4]; + + for (size_t iStep = 0; iStep < cSteps; iStep++) + { + pSteps[iStep].r = X.r * pC[iStep] + Y.r * pD[iStep]; + pSteps[iStep].g = X.g * pC[iStep] + Y.g * pD[iStep]; + pSteps[iStep].b = X.b * pC[iStep] + Y.b * pD[iStep]; + } + + + // Calculate color direction + Dir.r = Y.r - X.r; + Dir.g = Y.g - X.g; + Dir.b = Y.b - X.b; + + float fLen = (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b); + + if (fLen < (1.0f / 4096.0f)) + break; + + float fScale = fSteps / fLen; + + Dir.r *= fScale; + Dir.g *= fScale; + Dir.b *= fScale; + + + // Evaluate function, and derivatives + float d2X, d2Y; + HDRColorA dX, dY; + d2X = d2Y = dX.r = dX.g = dX.b = dY.r = dY.g = dY.b = 0.0f; + + for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++) + { + float fDot = (pPoints[iPoint].r - X.r) * Dir.r + + (pPoints[iPoint].g - X.g) * Dir.g + + (pPoints[iPoint].b - X.b) * Dir.b; + + + size_t iStep; + if (fDot <= 0.0f) + iStep = 0; + else if (fDot >= fSteps) + iStep = cSteps - 1; + else + iStep = static_cast(fDot + 0.5f); + + + HDRColorA Diff; + Diff.r = pSteps[iStep].r - pPoints[iPoint].r; + Diff.g = pSteps[iStep].g - pPoints[iPoint].g; + Diff.b = pSteps[iStep].b - pPoints[iPoint].b; + +#ifdef COLOR_WEIGHTS + float fC = pC[iStep] * pPoints[iPoint].a * (1.0f / 8.0f); + float fD = pD[iStep] * pPoints[iPoint].a * (1.0f / 8.0f); +#else + float fC = pC[iStep] * (1.0f / 8.0f); + float fD = pD[iStep] * (1.0f / 8.0f); +#endif // COLOR_WEIGHTS + + d2X += fC * pC[iStep]; + dX.r += fC * Diff.r; + dX.g += fC * Diff.g; + dX.b += fC * Diff.b; + + d2Y += fD * pD[iStep]; + dY.r += fD * Diff.r; + dY.g += fD * Diff.g; + dY.b += fD * Diff.b; + } + + // Move endpoints + if (d2X > 0.0f) + { + float f = -1.0f / d2X; + + X.r += dX.r * f; + X.g += dX.g * f; + X.b += dX.b * f; + } + + if (d2Y > 0.0f) + { + float f = -1.0f / d2Y; + + Y.r += dY.r * f; + Y.g += dY.g * f; + Y.b += dY.b * f; + } + + if ((dX.r * dX.r < fEpsilon) && (dX.g * dX.g < fEpsilon) && (dX.b * dX.b < fEpsilon) && + (dY.r * dY.r < fEpsilon) && (dY.g * dY.g < fEpsilon) && (dY.b * dY.b < fEpsilon)) + { + break; + } + } + + pX->r = X.r; pX->g = X.g; pX->b = X.b; + pY->r = Y.r; pY->g = Y.g; pY->b = Y.b; + } + + + //------------------------------------------------------------------------------------- + inline void DecodeBC1( + _Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, + _In_ const D3DX_BC1 *pBC, + bool isbc1) + { + assert(pColor && pBC); + static_assert(sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes"); + + static XMVECTORF32 s_Scale = { { { 1.f / 31.f, 1.f / 63.f, 1.f / 31.f, 1.f } } }; + + XMVECTOR clr0 = XMLoadU565(reinterpret_cast(&pBC->rgb[0])); + XMVECTOR clr1 = XMLoadU565(reinterpret_cast(&pBC->rgb[1])); + + clr0 = XMVectorMultiply(clr0, s_Scale); + clr1 = XMVectorMultiply(clr1, s_Scale); + + clr0 = XMVectorSwizzle<2, 1, 0, 3>(clr0); + clr1 = XMVectorSwizzle<2, 1, 0, 3>(clr1); + + clr0 = XMVectorSelect(g_XMIdentityR3, clr0, g_XMSelect1110); + clr1 = XMVectorSelect(g_XMIdentityR3, clr1, g_XMSelect1110); + + XMVECTOR clr2, clr3; + if (isbc1 && (pBC->rgb[0] <= pBC->rgb[1])) + { + clr2 = XMVectorLerp(clr0, clr1, 0.5f); + clr3 = XMVectorZero(); // Alpha of 0 + } + else + { + clr2 = XMVectorLerp(clr0, clr1, 1.f / 3.f); + clr3 = XMVectorLerp(clr0, clr1, 2.f / 3.f); + } + + uint32_t dw = pBC->bitmap; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 2) + { + switch (dw & 3) + { + case 0: pColor[i] = clr0; break; + case 1: pColor[i] = clr1; break; + case 2: pColor[i] = clr2; break; + + case 3: + default: pColor[i] = clr3; break; + } + } + } + + + //------------------------------------------------------------------------------------- + void EncodeBC1( + _Out_ D3DX_BC1 *pBC, + _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor, + bool bColorKey, + float threshold, + DWORD flags) + { + assert(pBC && pColor); + static_assert(sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes"); + + // Determine if we need to colorkey this block + size_t uSteps; + + if (bColorKey) + { + size_t uColorKey = 0; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + if (pColor[i].a < threshold) + uColorKey++; + } + + if (NUM_PIXELS_PER_BLOCK == uColorKey) + { + pBC->rgb[0] = 0x0000; + pBC->rgb[1] = 0xffff; + pBC->bitmap = 0xffffffff; + return; + } + + uSteps = (uColorKey > 0) ? 3 : 4; + } + else + { + uSteps = 4; + } + + // Quantize block to R56B5, using Floyd Stienberg error diffusion. This + // increases the chance that colors will map directly to the quantized + // axis endpoints. + HDRColorA Color[NUM_PIXELS_PER_BLOCK]; + HDRColorA Error[NUM_PIXELS_PER_BLOCK]; + + if (flags & BC_FLAGS_DITHER_RGB) + memset(Error, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(HDRColorA)); + + size_t i; + for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + HDRColorA Clr; + Clr.r = pColor[i].r; + Clr.g = pColor[i].g; + Clr.b = pColor[i].b; + + if (flags & BC_FLAGS_DITHER_RGB) + { + Clr.r += Error[i].r; + Clr.g += Error[i].g; + Clr.b += Error[i].b; + } + + Color[i].r = (float) static_cast(Clr.r * 31.0f + 0.5f) * (1.0f / 31.0f); + Color[i].g = (float) static_cast(Clr.g * 63.0f + 0.5f) * (1.0f / 63.0f); + Color[i].b = (float) static_cast(Clr.b * 31.0f + 0.5f) * (1.0f / 31.0f); + +#ifdef COLOR_WEIGHTS + Color[i].a = pColor[i].a; +#else + Color[i].a = 1.0f; +#endif // COLOR_WEIGHTS + + if (flags & BC_FLAGS_DITHER_RGB) + { + HDRColorA Diff; + Diff.r = Color[i].a * (Clr.r - Color[i].r); + Diff.g = Color[i].a * (Clr.g - Color[i].g); + Diff.b = Color[i].a * (Clr.b - Color[i].b); + + if (3 != (i & 3)) + { + assert(i < 15); + _Analysis_assume_(i < 15); + Error[i + 1].r += Diff.r * (7.0f / 16.0f); + Error[i + 1].g += Diff.g * (7.0f / 16.0f); + Error[i + 1].b += Diff.b * (7.0f / 16.0f); + } + + if (i < 12) + { + if (i & 3) + { + Error[i + 3].r += Diff.r * (3.0f / 16.0f); + Error[i + 3].g += Diff.g * (3.0f / 16.0f); + Error[i + 3].b += Diff.b * (3.0f / 16.0f); + } + + Error[i + 4].r += Diff.r * (5.0f / 16.0f); + Error[i + 4].g += Diff.g * (5.0f / 16.0f); + Error[i + 4].b += Diff.b * (5.0f / 16.0f); + + if (3 != (i & 3)) + { + assert(i < 11); + _Analysis_assume_(i < 11); + Error[i + 5].r += Diff.r * (1.0f / 16.0f); + Error[i + 5].g += Diff.g * (1.0f / 16.0f); + Error[i + 5].b += Diff.b * (1.0f / 16.0f); + } + } + } + + if (!(flags & BC_FLAGS_UNIFORM)) + { + Color[i].r *= g_Luminance.r; + Color[i].g *= g_Luminance.g; + Color[i].b *= g_Luminance.b; + } + } + + // Perform 6D root finding function to find two endpoints of color axis. + // Then quantize and sort the endpoints depending on mode. + HDRColorA ColorA, ColorB, ColorC, ColorD; + + OptimizeRGB(&ColorA, &ColorB, Color, uSteps, flags); + + if (flags & BC_FLAGS_UNIFORM) + { + ColorC = ColorA; + ColorD = ColorB; + } + else + { + ColorC.r = ColorA.r * g_LuminanceInv.r; + ColorC.g = ColorA.g * g_LuminanceInv.g; + ColorC.b = ColorA.b * g_LuminanceInv.b; + + ColorD.r = ColorB.r * g_LuminanceInv.r; + ColorD.g = ColorB.g * g_LuminanceInv.g; + ColorD.b = ColorB.b * g_LuminanceInv.b; + } + + uint16_t wColorA = Encode565(&ColorC); + uint16_t wColorB = Encode565(&ColorD); + + if ((uSteps == 4) && (wColorA == wColorB)) + { + pBC->rgb[0] = wColorA; + pBC->rgb[1] = wColorB; + pBC->bitmap = 0x00000000; + return; + } + + Decode565(&ColorC, wColorA); + Decode565(&ColorD, wColorB); + + if (flags & BC_FLAGS_UNIFORM) + { + ColorA = ColorC; + ColorB = ColorD; + } + else + { + ColorA.r = ColorC.r * g_Luminance.r; + ColorA.g = ColorC.g * g_Luminance.g; + ColorA.b = ColorC.b * g_Luminance.b; + + ColorB.r = ColorD.r * g_Luminance.r; + ColorB.g = ColorD.g * g_Luminance.g; + ColorB.b = ColorD.b * g_Luminance.b; + } + + // Calculate color steps + HDRColorA Step[4]; + + if ((3 == uSteps) == (wColorA <= wColorB)) + { + pBC->rgb[0] = wColorA; + pBC->rgb[1] = wColorB; + + Step[0] = ColorA; + Step[1] = ColorB; + } + else + { + pBC->rgb[0] = wColorB; + pBC->rgb[1] = wColorA; + + Step[0] = ColorB; + Step[1] = ColorA; + } + + static const size_t pSteps3[] = { 0, 2, 1 }; + static const size_t pSteps4[] = { 0, 2, 3, 1 }; + const size_t *pSteps; + + if (3 == uSteps) + { + pSteps = pSteps3; + + HDRColorALerp(&Step[2], &Step[0], &Step[1], 0.5f); + } + else + { + pSteps = pSteps4; + + HDRColorALerp(&Step[2], &Step[0], &Step[1], 1.0f / 3.0f); + HDRColorALerp(&Step[3], &Step[0], &Step[1], 2.0f / 3.0f); + } + + // Calculate color direction + HDRColorA Dir; + + Dir.r = Step[1].r - Step[0].r; + Dir.g = Step[1].g - Step[0].g; + Dir.b = Step[1].b - Step[0].b; + + float fSteps = (float)(uSteps - 1); + float fScale = (wColorA != wColorB) ? (fSteps / (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b)) : 0.0f; + + Dir.r *= fScale; + Dir.g *= fScale; + Dir.b *= fScale; + + // Encode colors + uint32_t dw = 0; + if (flags & BC_FLAGS_DITHER_RGB) + memset(Error, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(HDRColorA)); + + for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + if ((3 == uSteps) && (pColor[i].a < threshold)) + { + dw = (3 << 30) | (dw >> 2); + } + else + { + HDRColorA Clr; + if (flags & BC_FLAGS_UNIFORM) + { + Clr.r = pColor[i].r; + Clr.g = pColor[i].g; + Clr.b = pColor[i].b; + } + else + { + Clr.r = pColor[i].r * g_Luminance.r; + Clr.g = pColor[i].g * g_Luminance.g; + Clr.b = pColor[i].b * g_Luminance.b; + } + + if (flags & BC_FLAGS_DITHER_RGB) + { + Clr.r += Error[i].r; + Clr.g += Error[i].g; + Clr.b += Error[i].b; + } + + float fDot = (Clr.r - Step[0].r) * Dir.r + (Clr.g - Step[0].g) * Dir.g + (Clr.b - Step[0].b) * Dir.b; + uint32_t iStep; + + if (fDot <= 0.0f) + iStep = 0; + else if (fDot >= fSteps) + iStep = 1; + else + iStep = static_cast(pSteps[static_cast(fDot + 0.5f)]); + + dw = (iStep << 30) | (dw >> 2); + + if (flags & BC_FLAGS_DITHER_RGB) + { + HDRColorA Diff; + Diff.r = Color[i].a * (Clr.r - Step[iStep].r); + Diff.g = Color[i].a * (Clr.g - Step[iStep].g); + Diff.b = Color[i].a * (Clr.b - Step[iStep].b); + + if (3 != (i & 3)) + { + Error[i + 1].r += Diff.r * (7.0f / 16.0f); + Error[i + 1].g += Diff.g * (7.0f / 16.0f); + Error[i + 1].b += Diff.b * (7.0f / 16.0f); + } + + if (i < 12) + { + if (i & 3) + { + Error[i + 3].r += Diff.r * (3.0f / 16.0f); + Error[i + 3].g += Diff.g * (3.0f / 16.0f); + Error[i + 3].b += Diff.b * (3.0f / 16.0f); + } + + Error[i + 4].r += Diff.r * (5.0f / 16.0f); + Error[i + 4].g += Diff.g * (5.0f / 16.0f); + Error[i + 4].b += Diff.b * (5.0f / 16.0f); + + if (3 != (i & 3)) + { + Error[i + 5].r += Diff.r * (1.0f / 16.0f); + Error[i + 5].g += Diff.g * (1.0f / 16.0f); + Error[i + 5].b += Diff.b * (1.0f / 16.0f); + } + } + } + } + } + + pBC->bitmap = dw; + } + + //------------------------------------------------------------------------------------- +#ifdef COLOR_WEIGHTS + void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor) + { +#ifdef COLOR_AVG_0WEIGHTS + // Compute avg color + HDRColorA Color; + Color.r = pColor[0].r; + Color.g = pColor[0].g; + Color.b = pColor[0].b; + + for (size_t i = 1; i < NUM_PIXELS_PER_BLOCK; ++i) + { + Color.r += pColor[i].r; + Color.g += pColor[i].g; + Color.b += pColor[i].b; + } + + Color.r *= 1.0f / 16.0f; + Color.g *= 1.0f / 16.0f; + Color.b *= 1.0f / 16.0f; + + uint16_t wColor = Encode565(&Color); +#else + uint16_t wColor = 0x0000; +#endif // COLOR_AVG_0WEIGHTS + + // Encode solid block + pBC->rgb[0] = wColor; + pBC->rgb[1] = wColor; + pBC->bitmap = 0x00000000; + } +#endif // COLOR_WEIGHTS +} + + +//===================================================================================== +// Entry points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// BC1 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC) +{ + auto pBC1 = reinterpret_cast(pBC); + DecodeBC1(pColor, pBC1, true); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float threshold, DWORD flags) +{ + assert(pBC && pColor); + + HDRColorA Color[NUM_PIXELS_PER_BLOCK]; + + if (flags & BC_FLAGS_DITHER_A) + { + float fError[NUM_PIXELS_PER_BLOCK]; + memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float)); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + HDRColorA clr; + XMStoreFloat4(reinterpret_cast(&clr), pColor[i]); + + float fAlph = clr.a + fError[i]; + + Color[i].r = clr.r; + Color[i].g = clr.g; + Color[i].b = clr.b; + Color[i].a = (float) static_cast(clr.a + fError[i] + 0.5f); + + float fDiff = fAlph - Color[i].a; + + if (3 != (i & 3)) + { + assert(i < 15); + _Analysis_assume_(i < 15); + fError[i + 1] += fDiff * (7.0f / 16.0f); + } + + if (i < 12) + { + if (i & 3) + fError[i + 3] += fDiff * (3.0f / 16.0f); + + fError[i + 4] += fDiff * (5.0f / 16.0f); + + if (3 != (i & 3)) + { + assert(i < 11); + _Analysis_assume_(i < 11); + fError[i + 5] += fDiff * (1.0f / 16.0f); + } + } + } + } + else + { + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + XMStoreFloat4(reinterpret_cast(&Color[i]), pColor[i]); + } + } + + auto pBC1 = reinterpret_cast(pBC); + EncodeBC1(pBC1, Color, true, threshold, flags); +} + + +//------------------------------------------------------------------------------------- +// BC2 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes"); + + auto pBC2 = reinterpret_cast(pBC); + + // RGB part + DecodeBC1(pColor, &pBC2->bc1, false); + + // 4-bit alpha part + DWORD dw = pBC2->bitmap[0]; + + for (size_t i = 0; i < 8; ++i, dw >>= 4) + { +#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool") + pColor[i] = XMVectorSetW(pColor[i], (float)(dw & 0xf) * (1.0f / 15.0f)); + } + + dw = pBC2->bitmap[1]; + + for (size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 4) + pColor[i] = XMVectorSetW(pColor[i], (float)(dw & 0xf) * (1.0f / 15.0f)); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + assert(pBC && pColor); + static_assert(sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes"); + + HDRColorA Color[NUM_PIXELS_PER_BLOCK]; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + XMStoreFloat4(reinterpret_cast(&Color[i]), pColor[i]); + } + + auto pBC2 = reinterpret_cast(pBC); + + // 4-bit alpha part. Dithered using Floyd Stienberg error diffusion. + pBC2->bitmap[0] = 0; + pBC2->bitmap[1] = 0; + + float fError[NUM_PIXELS_PER_BLOCK]; + if (flags & BC_FLAGS_DITHER_A) + memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float)); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + float fAlph = Color[i].a; + if (flags & BC_FLAGS_DITHER_A) + fAlph += fError[i]; + + uint32_t u = (uint32_t) static_cast(fAlph * 15.0f + 0.5f); + + pBC2->bitmap[i >> 3] >>= 4; + pBC2->bitmap[i >> 3] |= (u << 28); + + if (flags & BC_FLAGS_DITHER_A) + { + float fDiff = fAlph - (float)u * (1.0f / 15.0f); + + if (3 != (i & 3)) + { + assert(i < 15); + _Analysis_assume_(i < 15); + fError[i + 1] += fDiff * (7.0f / 16.0f); + } + + if (i < 12) + { + if (i & 3) + fError[i + 3] += fDiff * (3.0f / 16.0f); + + fError[i + 4] += fDiff * (5.0f / 16.0f); + + if (3 != (i & 3)) + { + assert(i < 11); + _Analysis_assume_(i < 11); + fError[i + 5] += fDiff * (1.0f / 16.0f); + } + } + } + } + + // RGB part +#ifdef COLOR_WEIGHTS + if (!pBC2->bitmap[0] && !pBC2->bitmap[1]) + { + EncodeSolidBC1(pBC2->dxt1, Color); + return; + } +#endif // COLOR_WEIGHTS + + EncodeBC1(&pBC2->bc1, Color, false, 0.f, flags); +} + + +//------------------------------------------------------------------------------------- +// BC3 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes"); + + auto pBC3 = reinterpret_cast(pBC); + + // RGB part + DecodeBC1(pColor, &pBC3->bc1, false); + + // Adaptive 3-bit alpha part + float fAlpha[8]; + + fAlpha[0] = ((float)pBC3->alpha[0]) * (1.0f / 255.0f); + fAlpha[1] = ((float)pBC3->alpha[1]) * (1.0f / 255.0f); + + if (pBC3->alpha[0] > pBC3->alpha[1]) + { + for (size_t i = 1; i < 7; ++i) + fAlpha[i + 1] = (fAlpha[0] * (7 - i) + fAlpha[1] * i) * (1.0f / 7.0f); + } + else + { + for (size_t i = 1; i < 5; ++i) + fAlpha[i + 1] = (fAlpha[0] * (5 - i) + fAlpha[1] * i) * (1.0f / 5.0f); + + fAlpha[6] = 0.0f; + fAlpha[7] = 1.0f; + } + + DWORD dw = pBC3->bitmap[0] | (pBC3->bitmap[1] << 8) | (pBC3->bitmap[2] << 16); + + for (size_t i = 0; i < 8; ++i, dw >>= 3) + pColor[i] = XMVectorSetW(pColor[i], fAlpha[dw & 0x7]); + + dw = pBC3->bitmap[3] | (pBC3->bitmap[4] << 8) | (pBC3->bitmap[5] << 16); + + for (size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 3) + pColor[i] = XMVectorSetW(pColor[i], fAlpha[dw & 0x7]); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + assert(pBC && pColor); + static_assert(sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes"); + + HDRColorA Color[NUM_PIXELS_PER_BLOCK]; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + XMStoreFloat4(reinterpret_cast(&Color[i]), pColor[i]); + } + + auto pBC3 = reinterpret_cast(pBC); + + // Quantize block to A8, using Floyd Stienberg error diffusion. This + // increases the chance that colors will map directly to the quantized + // axis endpoints. + float fAlpha[NUM_PIXELS_PER_BLOCK]; + float fError[NUM_PIXELS_PER_BLOCK]; + + float fMinAlpha = Color[0].a; + float fMaxAlpha = Color[0].a; + + if (flags & BC_FLAGS_DITHER_A) + memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float)); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + float fAlph = Color[i].a; + if (flags & BC_FLAGS_DITHER_A) + fAlph += fError[i]; + + fAlpha[i] = static_cast(fAlph * 255.0f + 0.5f) * (1.0f / 255.0f); + + if (fAlpha[i] < fMinAlpha) + fMinAlpha = fAlpha[i]; + else if (fAlpha[i] > fMaxAlpha) + fMaxAlpha = fAlpha[i]; + + if (flags & BC_FLAGS_DITHER_A) + { + float fDiff = fAlph - fAlpha[i]; + + if (3 != (i & 3)) + { + assert(i < 15); + _Analysis_assume_(i < 15); + fError[i + 1] += fDiff * (7.0f / 16.0f); + } + + if (i < 12) + { + if (i & 3) + fError[i + 3] += fDiff * (3.0f / 16.0f); + + fError[i + 4] += fDiff * (5.0f / 16.0f); + + if (3 != (i & 3)) + { + assert(i < 11); + _Analysis_assume_(i < 11); + fError[i + 5] += fDiff * (1.0f / 16.0f); + } + } + } + } + +#ifdef COLOR_WEIGHTS + if (0.0f == fMaxAlpha) + { + EncodeSolidBC1(&pBC3->dxt1, Color); + pBC3->alpha[0] = 0x00; + pBC3->alpha[1] = 0x00; + memset(pBC3->bitmap, 0x00, 6); + } +#endif + + // RGB part + EncodeBC1(&pBC3->bc1, Color, false, 0.f, flags); + + // Alpha part + if (1.0f == fMinAlpha) + { + pBC3->alpha[0] = 0xff; + pBC3->alpha[1] = 0xff; + memset(pBC3->bitmap, 0x00, 6); + return; + } + + // Optimize and Quantize Min and Max values + size_t uSteps = ((0.0f == fMinAlpha) || (1.0f == fMaxAlpha)) ? 6 : 8; + + float fAlphaA, fAlphaB; + OptimizeAlpha(&fAlphaA, &fAlphaB, fAlpha, uSteps); + + uint8_t bAlphaA = (uint8_t) static_cast(fAlphaA * 255.0f + 0.5f); + uint8_t bAlphaB = (uint8_t) static_cast(fAlphaB * 255.0f + 0.5f); + + fAlphaA = (float)bAlphaA * (1.0f / 255.0f); + fAlphaB = (float)bAlphaB * (1.0f / 255.0f); + + // Setup block + if ((8 == uSteps) && (bAlphaA == bAlphaB)) + { + pBC3->alpha[0] = bAlphaA; + pBC3->alpha[1] = bAlphaB; + memset(pBC3->bitmap, 0x00, 6); + return; + } + + static const size_t pSteps6[] = { 0, 2, 3, 4, 5, 1 }; + static const size_t pSteps8[] = { 0, 2, 3, 4, 5, 6, 7, 1 }; + + const size_t *pSteps; + float fStep[8]; + + if (6 == uSteps) + { + pBC3->alpha[0] = bAlphaA; + pBC3->alpha[1] = bAlphaB; + + fStep[0] = fAlphaA; + fStep[1] = fAlphaB; + + for (size_t i = 1; i < 5; ++i) + fStep[i + 1] = (fStep[0] * (5 - i) + fStep[1] * i) * (1.0f / 5.0f); + + fStep[6] = 0.0f; + fStep[7] = 1.0f; + + pSteps = pSteps6; + } + else + { + pBC3->alpha[0] = bAlphaB; + pBC3->alpha[1] = bAlphaA; + + fStep[0] = fAlphaB; + fStep[1] = fAlphaA; + + for (size_t i = 1; i < 7; ++i) + fStep[i + 1] = (fStep[0] * (7 - i) + fStep[1] * i) * (1.0f / 7.0f); + + pSteps = pSteps8; + } + + // Encode alpha bitmap + float fSteps = (float)(uSteps - 1); + float fScale = (fStep[0] != fStep[1]) ? (fSteps / (fStep[1] - fStep[0])) : 0.0f; + + if (flags & BC_FLAGS_DITHER_A) + memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float)); + + for (size_t iSet = 0; iSet < 2; iSet++) + { + uint32_t dw = 0; + + size_t iMin = iSet * 8; + size_t iLim = iMin + 8; + + for (size_t i = iMin; i < iLim; ++i) + { + float fAlph = Color[i].a; + if (flags & BC_FLAGS_DITHER_A) + fAlph += fError[i]; + float fDot = (fAlph - fStep[0]) * fScale; + + uint32_t iStep; + if (fDot <= 0.0f) + iStep = ((6 == uSteps) && (fAlph <= fStep[0] * 0.5f)) ? 6 : 0; + else if (fDot >= fSteps) + iStep = ((6 == uSteps) && (fAlph >= (fStep[1] + 1.0f) * 0.5f)) ? 7 : 1; + else + iStep = static_cast(pSteps[static_cast(fDot + 0.5f)]); + + dw = (iStep << 21) | (dw >> 3); + + if (flags & BC_FLAGS_DITHER_A) + { + float fDiff = (fAlph - fStep[iStep]); + + if (3 != (i & 3)) + fError[i + 1] += fDiff * (7.0f / 16.0f); + + if (i < 12) + { + if (i & 3) + fError[i + 3] += fDiff * (3.0f / 16.0f); + + fError[i + 4] += fDiff * (5.0f / 16.0f); + + if (3 != (i & 3)) + fError[i + 5] += fDiff * (1.0f / 16.0f); + } + } + } + + pBC3->bitmap[0 + iSet * 3] = ((uint8_t *)&dw)[0]; + pBC3->bitmap[1 + iSet * 3] = ((uint8_t *)&dw)[1]; + pBC3->bitmap[2 + iSet * 3] = ((uint8_t *)&dw)[2]; + } +} diff --git a/Kits/DirectXTex/BC.h b/Kits/DirectXTex/BC.h new file mode 100644 index 0000000000000000000000000000000000000000..e7357166b10183c2f43ddfda16f903101bb34e1c --- /dev/null +++ b/Kits/DirectXTex/BC.h @@ -0,0 +1,332 @@ +//------------------------------------------------------------------------------------- +// BC.h +// +// Block-compression (BC) functionality +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +namespace DirectX +{ +//------------------------------------------------------------------------------------- +// Macros +//------------------------------------------------------------------------------------- + +// Because these are used in SAL annotations, they need to remain macros rather than const values +#define NUM_PIXELS_PER_BLOCK 16 + +//------------------------------------------------------------------------------------- +// Constants +//------------------------------------------------------------------------------------- + +enum BC_FLAGS +{ + BC_FLAGS_NONE = 0x0, + BC_FLAGS_DITHER_RGB = 0x10000, // Enables dithering for RGB colors for BC1-3 + BC_FLAGS_DITHER_A = 0x20000, // Enables dithering for Alpha channel for BC1-3 + BC_FLAGS_UNIFORM = 0x40000, // By default, uses perceptual weighting for BC1-3; this flag makes it a uniform weighting + BC_FLAGS_USE_3SUBSETS = 0x80000, // By default, BC7 skips mode 0 & 2; this flag adds those modes back + BC_FLAGS_FORCE_BC7_MODE6 = 0x100000, // BC7 should only use mode 6; skip other modes +}; + +//------------------------------------------------------------------------------------- +// Structures +//------------------------------------------------------------------------------------- +class LDRColorA; + +class HDRColorA +{ +public: + float r, g, b, a; + +public: + HDRColorA() = default; + HDRColorA(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) {} + HDRColorA(const HDRColorA& c) : r(c.r), g(c.g), b(c.b), a(c.a) {} + + // binary operators + HDRColorA operator + ( const HDRColorA& c ) const + { + return HDRColorA(r + c.r, g + c.g, b + c.b, a + c.a); + } + + HDRColorA operator - ( const HDRColorA& c ) const + { + return HDRColorA(r - c.r, g - c.g, b - c.b, a - c.a); + } + + HDRColorA operator * ( float f ) const + { + return HDRColorA(r * f, g * f, b * f, a * f); + } + + HDRColorA operator / ( float f ) const + { + float fInv = 1.0f / f; + return HDRColorA(r * fInv, g * fInv, b * fInv, a * fInv); + } + + float operator * ( const HDRColorA& c ) const + { + return r * c.r + g * c.g + b * c.b + a * c.a; + } + + // assignment operators + HDRColorA& operator += ( const HDRColorA& c ) + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; + } + + HDRColorA& operator -= ( const HDRColorA& c ) + { + r -= c.r; + g -= c.g; + b -= c.b; + a -= c.a; + return *this; + } + + HDRColorA& operator *= ( float f ) + { + r *= f; + g *= f; + b *= f; + a *= f; + return *this; + } + + HDRColorA& operator /= ( float f ) + { + float fInv = 1.0f / f; + r *= fInv; + g *= fInv; + b *= fInv; + a *= fInv; + return *this; + } + + HDRColorA& Clamp(_In_ float fMin, _In_ float fMax) + { + r = std::min(fMax, std::max(fMin, r)); + g = std::min(fMax, std::max(fMin, g)); + b = std::min(fMax, std::max(fMin, b)); + a = std::min(fMax, std::max(fMin, a)); + return *this; + } + + HDRColorA(const LDRColorA& c); + HDRColorA& operator = (const LDRColorA& c); + LDRColorA ToLDRColorA() const; +}; + +inline HDRColorA* HDRColorALerp(_Out_ HDRColorA *pOut, _In_ const HDRColorA *pC1, _In_ const HDRColorA *pC2, _In_ float s) +{ + pOut->r = pC1->r + s * (pC2->r - pC1->r); + pOut->g = pC1->g + s * (pC2->g - pC1->g); + pOut->b = pC1->b + s * (pC2->b - pC1->b); + pOut->a = pC1->a + s * (pC2->a - pC1->a); + return pOut; +} + +#pragma pack(push,1) +// BC1/DXT1 compression (4 bits per texel) +struct D3DX_BC1 +{ + uint16_t rgb[2]; // 565 colors + uint32_t bitmap; // 2bpp rgb bitmap +}; + +// BC2/DXT2/3 compression (8 bits per texel) +struct D3DX_BC2 +{ + uint32_t bitmap[2]; // 4bpp alpha bitmap + D3DX_BC1 bc1; // BC1 rgb data +}; + +// BC3/DXT4/5 compression (8 bits per texel) +struct D3DX_BC3 +{ + uint8_t alpha[2]; // alpha values + uint8_t bitmap[6]; // 3bpp alpha bitmap + D3DX_BC1 bc1; // BC1 rgb data +}; +#pragma pack(pop) + +//------------------------------------------------------------------------------------- +// Templates +//------------------------------------------------------------------------------------- +#pragma warning(push) +#pragma warning(disable : 4127) +template void OptimizeAlpha(float *pX, float *pY, const float *pPoints, size_t cSteps) +{ + static const float pC6[] = { 5.0f / 5.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f, 1.0f / 5.0f, 0.0f / 5.0f }; + static const float pD6[] = { 0.0f / 5.0f, 1.0f / 5.0f, 2.0f / 5.0f, 3.0f / 5.0f, 4.0f / 5.0f, 5.0f / 5.0f }; + static const float pC8[] = { 7.0f / 7.0f, 6.0f / 7.0f, 5.0f / 7.0f, 4.0f / 7.0f, 3.0f / 7.0f, 2.0f / 7.0f, 1.0f / 7.0f, 0.0f / 7.0f }; + static const float pD8[] = { 0.0f / 7.0f, 1.0f / 7.0f, 2.0f / 7.0f, 3.0f / 7.0f, 4.0f / 7.0f, 5.0f / 7.0f, 6.0f / 7.0f, 7.0f / 7.0f }; + + const float *pC = (6 == cSteps) ? pC6 : pC8; + const float *pD = (6 == cSteps) ? pD6 : pD8; + + const float MAX_VALUE = 1.0f; + const float MIN_VALUE = (bRange) ? -1.0f : 0.0f; + + // Find Min and Max points, as starting point + float fX = MAX_VALUE; + float fY = MIN_VALUE; + + if (8 == cSteps) + { + for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++) + { + if (pPoints[iPoint] < fX) + fX = pPoints[iPoint]; + + if (pPoints[iPoint] > fY) + fY = pPoints[iPoint]; + } + } + else + { + for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++) + { + if (pPoints[iPoint] < fX && pPoints[iPoint] > MIN_VALUE) + fX = pPoints[iPoint]; + + if (pPoints[iPoint] > fY && pPoints[iPoint] < MAX_VALUE) + fY = pPoints[iPoint]; + } + + if (fX == fY) + { + fY = MAX_VALUE; + } + } + + // Use Newton's Method to find local minima of sum-of-squares error. + float fSteps = (float)(cSteps - 1); + + for (size_t iIteration = 0; iIteration < 8; iIteration++) + { + float fScale; + + if ((fY - fX) < (1.0f / 256.0f)) + break; + + fScale = fSteps / (fY - fX); + + // Calculate new steps + float pSteps[8]; + + for (size_t iStep = 0; iStep < cSteps; iStep++) + pSteps[iStep] = pC[iStep] * fX + pD[iStep] * fY; + + if (6 == cSteps) + { + pSteps[6] = MIN_VALUE; + pSteps[7] = MAX_VALUE; + } + + // Evaluate function, and derivatives + float dX = 0.0f; + float dY = 0.0f; + float d2X = 0.0f; + float d2Y = 0.0f; + + for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++) + { + float fDot = (pPoints[iPoint] - fX) * fScale; + + size_t iStep; + + if (fDot <= 0.0f) + iStep = ((6 == cSteps) && (pPoints[iPoint] <= fX * 0.5f)) ? 6 : 0; + else if (fDot >= fSteps) + iStep = ((6 == cSteps) && (pPoints[iPoint] >= (fY + 1.0f) * 0.5f)) ? 7 : (cSteps - 1); + else + iStep = static_cast(fDot + 0.5f); + + + if (iStep < cSteps) + { + // D3DX had this computation backwards (pPoints[iPoint] - pSteps[iStep]) + // this fix improves RMS of the alpha component + float fDiff = pSteps[iStep] - pPoints[iPoint]; + + dX += pC[iStep] * fDiff; + d2X += pC[iStep] * pC[iStep]; + + dY += pD[iStep] * fDiff; + d2Y += pD[iStep] * pD[iStep]; + } + } + + // Move endpoints + if (d2X > 0.0f) + fX -= dX / d2X; + + if (d2Y > 0.0f) + fY -= dY / d2Y; + + if (fX > fY) + { + float f = fX; fX = fY; fY = f; + } + + if ((dX * dX < (1.0f / 64.0f)) && (dY * dY < (1.0f / 64.0f))) + break; + } + + *pX = (fX < MIN_VALUE) ? MIN_VALUE : (fX > MAX_VALUE) ? MAX_VALUE : fX; + *pY = (fY < MIN_VALUE) ? MIN_VALUE : (fY > MAX_VALUE) ? MAX_VALUE : fY; +} +#pragma warning(pop) + +//------------------------------------------------------------------------------------- +// Functions +//------------------------------------------------------------------------------------- + +typedef void (*BC_DECODE)(XMVECTOR *pColor, const uint8_t *pBC); +typedef void (*BC_ENCODE)(uint8_t *pDXT, const XMVECTOR *pColor, DWORD flags); + +void D3DXDecodeBC1(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC); +void D3DXDecodeBC2(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); +void D3DXDecodeBC3(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); +void D3DXDecodeBC4U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC); +void D3DXDecodeBC4S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC); +void D3DXDecodeBC5U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); +void D3DXDecodeBC5S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); +void D3DXDecodeBC6HU(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); +void D3DXDecodeBC6HS(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); +void D3DXDecodeBC7(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC); + +void D3DXEncodeBC1(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ float threshold, _In_ DWORD flags); + // BC1 requires one additional parameter, so it doesn't match signature of BC_ENCODE above + +void D3DXEncodeBC2(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC3(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC4U(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC4S(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC5U(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC5S(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC6HU(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC6HS(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); +void D3DXEncodeBC7(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags); + +}; // namespace diff --git a/Kits/DirectXTex/BC4BC5.cpp b/Kits/DirectXTex/BC4BC5.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8824df4c27b96ba1367cabf430e4c2daa2b1c542 --- /dev/null +++ b/Kits/DirectXTex/BC4BC5.cpp @@ -0,0 +1,566 @@ +//------------------------------------------------------------------------------------- +// BC4BC5.cpp +// +// Block-compression (BC) functionality for BC4 and BC5 (DirectX 10 texture compression) +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "BC.h" + +using namespace DirectX; + +//------------------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------------------ + +// Because these are used in SAL annotations, they need to remain macros rather than const values +#define BLOCK_LEN 4 +// length of each block in texel + +#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN) +// total texels in a 4x4 block. + +namespace +{ + //------------------------------------------------------------------------------------ + // Structures + //------------------------------------------------------------------------------------- + +#pragma warning(push) +#pragma warning(disable : 4201) + + // BC4U/BC5U + struct BC4_UNORM + { + float R(size_t uOffset) const + { + size_t uIndex = GetIndex(uOffset); + return DecodeFromIndex(uIndex); + } + + float DecodeFromIndex(size_t uIndex) const + { + if (uIndex == 0) + return red_0 / 255.0f; + if (uIndex == 1) + return red_1 / 255.0f; + float fred_0 = red_0 / 255.0f; + float fred_1 = red_1 / 255.0f; + if (red_0 > red_1) + { + uIndex -= 1; + return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f; + } + else + { + if (uIndex == 6) + return 0.0f; + if (uIndex == 7) + return 1.0f; + uIndex -= 1; + return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f; + } + } + + size_t GetIndex(size_t uOffset) const + { + return (size_t)((data >> (3 * uOffset + 16)) & 0x07); + } + + void SetIndex(size_t uOffset, size_t uIndex) + { + data &= ~((uint64_t)0x07 << (3 * uOffset + 16)); + data |= ((uint64_t)uIndex << (3 * uOffset + 16)); + } + + union + { + struct + { + uint8_t red_0; + uint8_t red_1; + uint8_t indices[6]; + }; + uint64_t data; + }; + }; + + // BC4S/BC5S + struct BC4_SNORM + { + float R(size_t uOffset) const + { + size_t uIndex = GetIndex(uOffset); + return DecodeFromIndex(uIndex); + } + + float DecodeFromIndex(size_t uIndex) const + { + int8_t sred_0 = (red_0 == -128) ? -127 : red_0; + int8_t sred_1 = (red_1 == -128) ? -127 : red_1; + + if (uIndex == 0) + return sred_0 / 127.0f; + if (uIndex == 1) + return sred_1 / 127.0f; + float fred_0 = sred_0 / 127.0f; + float fred_1 = sred_1 / 127.0f; + if (red_0 > red_1) + { + uIndex -= 1; + return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f; + } + else + { + if (uIndex == 6) + return -1.0f; + if (uIndex == 7) + return 1.0f; + uIndex -= 1; + return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f; + } + } + + size_t GetIndex(size_t uOffset) const + { + return (size_t)((data >> (3 * uOffset + 16)) & 0x07); + } + + void SetIndex(size_t uOffset, size_t uIndex) + { + data &= ~((uint64_t)0x07 << (3 * uOffset + 16)); + data |= ((uint64_t)uIndex << (3 * uOffset + 16)); + } + + union + { + struct + { + int8_t red_0; + int8_t red_1; + uint8_t indices[6]; + }; + uint64_t data; + }; + }; + +#pragma warning(pop) + + //------------------------------------------------------------------------------------- + // Convert a floating point value to an 8-bit SNORM + //------------------------------------------------------------------------------------- + void inline FloatToSNorm(_In_ float fVal, _Out_ int8_t *piSNorm) + { + const uint32_t dwMostNeg = (1 << (8 * sizeof(int8_t) - 1)); + + if (_isnan(fVal)) + fVal = 0; + else + if (fVal > 1) + fVal = 1; // Clamp to 1 + else + if (fVal < -1) + fVal = -1; // Clamp to -1 + + fVal = fVal * (int8_t)(dwMostNeg - 1); + + if (fVal >= 0) + fVal += .5f; + else + fVal -= .5f; + + *piSNorm = (int8_t)(fVal); + } + + + //------------------------------------------------------------------------------ + void FindEndPointsBC4U( + _In_reads_(BLOCK_SIZE) const float theTexelsU[], + _Out_ uint8_t &endpointU_0, + _Out_ uint8_t &endpointU_1) + { + // The boundary of codec for signed/unsigned format + const float MIN_NORM = 0.f; + const float MAX_NORM = 1.f; + + // Find max/min of input texels + float fBlockMax = theTexelsU[0]; + float fBlockMin = theTexelsU[0]; + for (size_t i = 0; i < BLOCK_SIZE; ++i) + { + if (theTexelsU[i] < fBlockMin) + { + fBlockMin = theTexelsU[i]; + } + else if (theTexelsU[i] > fBlockMax) + { + fBlockMax = theTexelsU[i]; + } + } + + // If there are boundary values in input texels, should use 4 interpolated color values to guarantee + // the exact code of the boundary values. + bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax); + + // Using Optimize + float fStart, fEnd; + + if (!bUsing4BlockCodec) + { + // 6 interpolated color values + OptimizeAlpha(&fStart, &fEnd, theTexelsU, 8); + + uint8_t iStart = static_cast(fStart * 255.0f); + uint8_t iEnd = static_cast(fEnd * 255.0f); + + endpointU_0 = iEnd; + endpointU_1 = iStart; + } + else + { + // 4 interpolated color values + OptimizeAlpha(&fStart, &fEnd, theTexelsU, 6); + + uint8_t iStart = static_cast(fStart * 255.0f); + uint8_t iEnd = static_cast(fEnd * 255.0f); + + endpointU_1 = iEnd; + endpointU_0 = iStart; + } + } + + void FindEndPointsBC4S( + _In_reads_(BLOCK_SIZE) const float theTexelsU[], + _Out_ int8_t &endpointU_0, + _Out_ int8_t &endpointU_1) + { + // The boundary of codec for signed/unsigned format + const float MIN_NORM = -1.f; + const float MAX_NORM = 1.f; + + // Find max/min of input texels + float fBlockMax = theTexelsU[0]; + float fBlockMin = theTexelsU[0]; + for (size_t i = 0; i < BLOCK_SIZE; ++i) + { + if (theTexelsU[i] < fBlockMin) + { + fBlockMin = theTexelsU[i]; + } + else if (theTexelsU[i] > fBlockMax) + { + fBlockMax = theTexelsU[i]; + } + } + + // If there are boundary values in input texels, should use 4 interpolated color values to guarantee + // the exact code of the boundary values. + bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax); + + // Using Optimize + float fStart, fEnd; + + if (!bUsing4BlockCodec) + { + // 6 interpolated color values + OptimizeAlpha(&fStart, &fEnd, theTexelsU, 8); + + int8_t iStart, iEnd; + FloatToSNorm(fStart, &iStart); + FloatToSNorm(fEnd, &iEnd); + + endpointU_0 = iEnd; + endpointU_1 = iStart; + } + else + { + // 4 interpolated color values + OptimizeAlpha(&fStart, &fEnd, theTexelsU, 6); + + int8_t iStart, iEnd; + FloatToSNorm(fStart, &iStart); + FloatToSNorm(fEnd, &iEnd); + + endpointU_1 = iEnd; + endpointU_0 = iStart; + } + } + + + //------------------------------------------------------------------------------ + inline void FindEndPointsBC5U( + _In_reads_(BLOCK_SIZE) const float theTexelsU[], + _In_reads_(BLOCK_SIZE) const float theTexelsV[], + _Out_ uint8_t &endpointU_0, + _Out_ uint8_t &endpointU_1, + _Out_ uint8_t &endpointV_0, + _Out_ uint8_t &endpointV_1) + { + //Encoding the U and V channel by BC4 codec separately. + FindEndPointsBC4U(theTexelsU, endpointU_0, endpointU_1); + FindEndPointsBC4U(theTexelsV, endpointV_0, endpointV_1); + } + + inline void FindEndPointsBC5S( + _In_reads_(BLOCK_SIZE) const float theTexelsU[], + _In_reads_(BLOCK_SIZE) const float theTexelsV[], + _Out_ int8_t &endpointU_0, + _Out_ int8_t &endpointU_1, + _Out_ int8_t &endpointV_0, + _Out_ int8_t &endpointV_1) + { + //Encoding the U and V channel by BC4 codec separately. + FindEndPointsBC4S(theTexelsU, endpointU_0, endpointU_1); + FindEndPointsBC4S(theTexelsV, endpointV_0, endpointV_1); + } + + + //------------------------------------------------------------------------------ + void FindClosestUNORM( + _Inout_ BC4_UNORM* pBC, + _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[]) + { + float rGradient[8]; + for (size_t i = 0; i < 8; ++i) + { + rGradient[i] = pBC->DecodeFromIndex(i); + } + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + size_t uBestIndex = 0; + float fBestDelta = 100000; + for (size_t uIndex = 0; uIndex < 8; uIndex++) + { + float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]); + if (fCurrentDelta < fBestDelta) + { + uBestIndex = uIndex; + fBestDelta = fCurrentDelta; + } + } + pBC->SetIndex(i, uBestIndex); + } + } + + void FindClosestSNORM( + _Inout_ BC4_SNORM* pBC, + _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[]) + { + float rGradient[8]; + for (size_t i = 0; i < 8; ++i) + { + rGradient[i] = pBC->DecodeFromIndex(i); + } + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + size_t uBestIndex = 0; + float fBestDelta = 100000; + for (size_t uIndex = 0; uIndex < 8; uIndex++) + { + float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]); + if (fCurrentDelta < fBestDelta) + { + uBestIndex = uIndex; + fBestDelta = fCurrentDelta; + } + } + pBC->SetIndex(i, uBestIndex); + } + } +} + + +//===================================================================================== +// Entry points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// BC4 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC4U(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes"); + + auto pBC4 = reinterpret_cast(pBC); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { +#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool") + pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f); + } +} + +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes"); + + auto pBC4 = reinterpret_cast(pBC); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { +#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool") + pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f); + } +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC4U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + UNREFERENCED_PARAMETER(flags); + + assert(pBC && pColor); + static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes"); + + memset(pBC, 0, sizeof(BC4_UNORM)); + auto pBC4 = reinterpret_cast(pBC); + float theTexelsU[NUM_PIXELS_PER_BLOCK]; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + theTexelsU[i] = XMVectorGetX(pColor[i]); + } + + FindEndPointsBC4U(theTexelsU, pBC4->red_0, pBC4->red_1); + FindClosestUNORM(pBC4, theTexelsU); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC4S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + UNREFERENCED_PARAMETER(flags); + + assert(pBC && pColor); + static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes"); + + memset(pBC, 0, sizeof(BC4_UNORM)); + auto pBC4 = reinterpret_cast(pBC); + float theTexelsU[NUM_PIXELS_PER_BLOCK]; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + theTexelsU[i] = XMVectorGetX(pColor[i]); + } + + FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1); + FindClosestSNORM(pBC4, theTexelsU); +} + + +//------------------------------------------------------------------------------------- +// BC5 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes"); + + auto pBCR = reinterpret_cast(pBC); + auto pBCG = reinterpret_cast(pBC + sizeof(BC4_UNORM)); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { +#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool") + pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f); + } +} + +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes"); + + auto pBCR = reinterpret_cast(pBC); + auto pBCG = reinterpret_cast(pBC + sizeof(BC4_SNORM)); + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { +#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool") + pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f); + } +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC5U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + UNREFERENCED_PARAMETER(flags); + + assert(pBC && pColor); + static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes"); + + memset(pBC, 0, sizeof(BC4_UNORM) * 2); + auto pBCR = reinterpret_cast(pBC); + auto pBCG = reinterpret_cast(pBC + sizeof(BC4_UNORM)); + float theTexelsU[NUM_PIXELS_PER_BLOCK]; + float theTexelsV[NUM_PIXELS_PER_BLOCK]; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + XMFLOAT4A clr; + XMStoreFloat4A(&clr, pColor[i]); + theTexelsU[i] = clr.x; + theTexelsV[i] = clr.y; + } + + FindEndPointsBC5U( + theTexelsU, + theTexelsV, + pBCR->red_0, + pBCR->red_1, + pBCG->red_0, + pBCG->red_1); + + FindClosestUNORM(pBCR, theTexelsU); + FindClosestUNORM(pBCG, theTexelsV); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC5S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + UNREFERENCED_PARAMETER(flags); + + assert(pBC && pColor); + static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes"); + + memset(pBC, 0, sizeof(BC4_UNORM) * 2); + auto pBCR = reinterpret_cast(pBC); + auto pBCG = reinterpret_cast(pBC + sizeof(BC4_SNORM)); + float theTexelsU[NUM_PIXELS_PER_BLOCK]; + float theTexelsV[NUM_PIXELS_PER_BLOCK]; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + XMFLOAT4A clr; + XMStoreFloat4A(&clr, pColor[i]); + theTexelsU[i] = clr.x; + theTexelsV[i] = clr.y; + } + + FindEndPointsBC5S( + theTexelsU, + theTexelsV, + pBCR->red_0, + pBCR->red_1, + pBCG->red_0, + pBCG->red_1); + + FindClosestSNORM(pBCR, theTexelsU); + FindClosestSNORM(pBCG, theTexelsV); +} \ No newline at end of file diff --git a/Kits/DirectXTex/BC6HBC7.cpp b/Kits/DirectXTex/BC6HBC7.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b98eef11411173977a5cf901317a7a33cc7ab12c --- /dev/null +++ b/Kits/DirectXTex/BC6HBC7.cpp @@ -0,0 +1,3470 @@ +//------------------------------------------------------------------------------------- +// BC6HBC7.cpp +// +// Block-compression (BC) functionality for BC6H and BC7 (DirectX 11 texture compression) +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "BC.h" + +using namespace DirectX; +using namespace DirectX::PackedVector; + +//------------------------------------------------------------------------------------- +// Macros +//------------------------------------------------------------------------------------- + +#define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x)) + +// Because these are used in SAL annotations, they need to remain macros rather than const values +#define BC6H_MAX_REGIONS 2 +#define BC6H_MAX_INDICES 16 +#define BC7_MAX_REGIONS 3 +#define BC7_MAX_INDICES 16 + +namespace +{ + //------------------------------------------------------------------------------------- + // Constants + //------------------------------------------------------------------------------------- + + const uint16_t F16S_MASK = 0x8000; // f16 sign mask + const uint16_t F16EM_MASK = 0x7fff; // f16 exp & mantissa mask + const uint16_t F16MAX = 0x7bff; // MAXFLT bit pattern for XMHALF + + const size_t BC6H_NUM_CHANNELS = 3; + const size_t BC6H_MAX_SHAPES = 32; + + const size_t BC7_NUM_CHANNELS = 4; + const size_t BC7_MAX_SHAPES = 64; + + const int32_t BC67_WEIGHT_MAX = 64; + const uint32_t BC67_WEIGHT_SHIFT = 6; + const int32_t BC67_WEIGHT_ROUND = 32; + + const float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f); + const float pC3[] = { 2.0f / 2.0f, 1.0f / 2.0f, 0.0f / 2.0f }; + const float pD3[] = { 0.0f / 2.0f, 1.0f / 2.0f, 2.0f / 2.0f }; + const float pC4[] = { 3.0f / 3.0f, 2.0f / 3.0f, 1.0f / 3.0f, 0.0f / 3.0f }; + const float pD4[] = { 0.0f / 3.0f, 1.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f }; + + // Partition, Shape, Pixel (index into 4x4 block) + const uint8_t g_aPartitionTable[3][64][16] = + { + { // 1 Region case has no subsets (all 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 }, + { 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 }, + { 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0 } + }, + + { // BC6H/BC7 Partition Set for 2 Subsets + { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, // Shape 0 + { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 }, // Shape 1 + { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, // Shape 2 + { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, // Shape 3 + { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 }, // Shape 4 + { 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // Shape 5 + { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // Shape 6 + { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, // Shape 7 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 }, // Shape 8 + { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 9 + { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // Shape 10 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 }, // Shape 11 + { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 12 + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 13 + { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 14 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, // Shape 15 + { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 }, // Shape 16 + { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // Shape 17 + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 }, // Shape 18 + { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, // Shape 19 + { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // Shape 20 + { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 }, // Shape 21 + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, // Shape 22 + { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, // Shape 23 + { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, // Shape 24 + { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, // Shape 25 + { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 }, // Shape 26 + { 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 }, // Shape 27 + { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 }, // Shape 28 + { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // Shape 29 + { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 }, // Shape 30 + { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 }, // Shape 31 + + // BC7 Partition Set for 2 Subsets (second-half) + { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, // Shape 32 + { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 }, // Shape 33 + { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 }, // Shape 34 + { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 }, // Shape 35 + { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 }, // Shape 36 + { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 }, // Shape 37 + { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 }, // Shape 38 + { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, // Shape 39 + { 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 }, // Shape 40 + { 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 }, // Shape 41 + { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 }, // Shape 42 + { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 }, // Shape 43 + { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }, // Shape 44 + { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 }, // Shape 45 + { 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 }, // Shape 46 + { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Shape 47 + { 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, // Shape 48 + { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, // Shape 49 + { 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 }, // Shape 50 + { 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 }, // Shape 51 + { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 }, // Shape 52 + { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, // Shape 53 + { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 }, // Shape 54 + { 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 }, // Shape 55 + { 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, // Shape 56 + { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 }, // Shape 57 + { 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, // Shape 58 + { 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 }, // Shape 59 + { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, // Shape 60 + { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // Shape 61 + { 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 }, // Shape 62 + { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 } // Shape 63 + }, + + { // BC7 Partition Set for 3 Subsets + { 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 }, // Shape 0 + { 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 }, // Shape 1 + { 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 }, // Shape 2 + { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 }, // Shape 3 + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 }, // Shape 4 + { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 }, // Shape 5 + { 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 6 + { 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 }, // Shape 7 + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 }, // Shape 8 + { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 }, // Shape 9 + { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 10 + { 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 }, // Shape 11 + { 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 }, // Shape 12 + { 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 }, // Shape 13 + { 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 }, // Shape 14 + { 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 }, // Shape 15 + { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 }, // Shape 16 + { 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 }, // Shape 17 + { 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 }, // Shape 18 + { 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 }, // Shape 19 + { 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 }, // Shape 20 + { 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 }, // Shape 21 + { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 }, // Shape 22 + { 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 }, // Shape 23 + { 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 }, // Shape 24 + { 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 }, // Shape 25 + { 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 }, // Shape 26 + { 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 }, // Shape 27 + { 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 }, // Shape 28 + { 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 }, // Shape 29 + { 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 }, // Shape 30 + { 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 }, // Shape 31 + { 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 }, // Shape 32 + { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 }, // Shape 33 + { 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 }, // Shape 34 + { 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 }, // Shape 35 + { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 }, // Shape 36 + { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 }, // Shape 37 + { 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 }, // Shape 38 + { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 }, // Shape 39 + { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 }, // Shape 40 + { 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 41 + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 }, // Shape 42 + { 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 }, // Shape 43 + { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 }, // Shape 44 + { 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 }, // Shape 45 + { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 }, // Shape 46 + { 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 }, // Shape 47 + { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 }, // Shape 48 + { 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 }, // Shape 49 + { 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 }, // Shape 50 + { 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 }, // Shape 51 + { 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 }, // Shape 52 + { 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 }, // Shape 53 + { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 }, // Shape 54 + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 }, // Shape 55 + { 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 56 + { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 }, // Shape 57 + { 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 }, // Shape 58 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 }, // Shape 59 + { 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 }, // Shape 60 + { 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 }, // Shape 61 + { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 62 + { 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 } // Shape 63 + } + }; + + // Partition, Shape, Fixup + const uint8_t g_aFixUp[3][64][3] = + { + { // No fix-ups for 1st subset for BC6H or BC7 + { 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 },{ 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 },{ 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 },{ 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 }, + { 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 },{ 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 } + }, + + { // BC6H/BC7 Partition Set Fixups for 2 Subsets + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0, 2, 0 },{ 0, 8, 0 },{ 0, 2, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0, 8, 0 },{ 0,15, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + { 0, 8, 0 },{ 0, 8, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + + // BC7 Partition Set Fixups for 2 Subsets (second-half) + { 0,15, 0 },{ 0,15, 0 },{ 0, 6, 0 },{ 0, 8, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0, 2, 0 },{ 0, 8, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + { 0, 2, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0, 6, 0 }, + { 0, 6, 0 },{ 0, 2, 0 },{ 0, 6, 0 },{ 0, 8, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0, 2, 0 },{ 0, 2, 0 }, + { 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 },{ 0,15, 0 }, + { 0,15, 0 },{ 0, 2, 0 },{ 0, 2, 0 },{ 0,15, 0 } + }, + + { // BC7 Partition Set Fixups for 3 Subsets + { 0, 3,15 },{ 0, 3, 8 },{ 0,15, 8 },{ 0,15, 3 }, + { 0, 8,15 },{ 0, 3,15 },{ 0,15, 3 },{ 0,15, 8 }, + { 0, 8,15 },{ 0, 8,15 },{ 0, 6,15 },{ 0, 6,15 }, + { 0, 6,15 },{ 0, 5,15 },{ 0, 3,15 },{ 0, 3, 8 }, + { 0, 3,15 },{ 0, 3, 8 },{ 0, 8,15 },{ 0,15, 3 }, + { 0, 3,15 },{ 0, 3, 8 },{ 0, 6,15 },{ 0,10, 8 }, + { 0, 5, 3 },{ 0, 8,15 },{ 0, 8, 6 },{ 0, 6,10 }, + { 0, 8,15 },{ 0, 5,15 },{ 0,15,10 },{ 0,15, 8 }, + { 0, 8,15 },{ 0,15, 3 },{ 0, 3,15 },{ 0, 5,10 }, + { 0, 6,10 },{ 0,10, 8 },{ 0, 8, 9 },{ 0,15,10 }, + { 0,15, 6 },{ 0, 3,15 },{ 0,15, 8 },{ 0, 5,15 }, + { 0,15, 3 },{ 0,15, 6 },{ 0,15, 6 },{ 0,15, 8 }, + { 0, 3,15 },{ 0,15, 3 },{ 0, 5,15 },{ 0, 5,15 }, + { 0, 5,15 },{ 0, 8,15 },{ 0, 5,15 },{ 0,10,15 }, + { 0, 5,15 },{ 0,10,15 },{ 0, 8,15 },{ 0,13,15 }, + { 0,15, 3 },{ 0,12,15 },{ 0, 3,15 },{ 0, 3, 8 } + } + }; + + const int g_aWeights2[] = { 0, 21, 43, 64 }; + const int g_aWeights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + const int g_aWeights4[] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; +} + +namespace DirectX +{ + class LDRColorA + { + public: + uint8_t r, g, b, a; + + LDRColorA() = default; + LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) : r(_r), g(_g), b(_b), a(_a) {} + + const uint8_t& operator [] (_In_range_(0, 3) size_t uElement) const + { + switch (uElement) + { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: assert(false); return r; + } + } + + uint8_t& operator [] (_In_range_(0, 3) size_t uElement) + { + switch (uElement) + { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: assert(false); return r; + } + } + + LDRColorA operator = (_In_ const HDRColorA& c) + { + LDRColorA ret; + HDRColorA tmp(c); + tmp = tmp.Clamp(0.0f, 1.0f) * 255.0f; + ret.r = uint8_t(tmp.r + 0.001f); + ret.g = uint8_t(tmp.g + 0.001f); + ret.b = uint8_t(tmp.b + 0.001f); + ret.a = uint8_t(tmp.a + 0.001f); + return ret; + } + + static void InterpolateRGB(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ _In_range_(2, 4) size_t wcprec, _Out_ LDRColorA& out) + { + const int* aWeights = nullptr; + switch (wcprec) + { + case 2: aWeights = g_aWeights2; assert(wc < 4); _Analysis_assume_(wc < 4); break; + case 3: aWeights = g_aWeights3; assert(wc < 8); _Analysis_assume_(wc < 8); break; + case 4: aWeights = g_aWeights4; assert(wc < 16); _Analysis_assume_(wc < 16); break; + default: assert(false); out.r = out.g = out.b = 0; return; + } + out.r = uint8_t((uint32_t(c0.r) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.r) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + out.g = uint8_t((uint32_t(c0.g) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.g) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + out.b = uint8_t((uint32_t(c0.b) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.b) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + } + + static void InterpolateA(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wa, _In_range_(2, 4) _In_ size_t waprec, _Out_ LDRColorA& out) + { + const int* aWeights = nullptr; + switch (waprec) + { + case 2: aWeights = g_aWeights2; assert(wa < 4); _Analysis_assume_(wa < 4); break; + case 3: aWeights = g_aWeights3; assert(wa < 8); _Analysis_assume_(wa < 8); break; + case 4: aWeights = g_aWeights4; assert(wa < 16); _Analysis_assume_(wa < 16); break; + default: assert(false); out.a = 0; return; + } + out.a = uint8_t((uint32_t(c0.a) * uint32_t(BC67_WEIGHT_MAX - aWeights[wa]) + uint32_t(c1.a) * uint32_t(aWeights[wa]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT); + } + + static void Interpolate(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ size_t wa, _In_ _In_range_(2, 4) size_t wcprec, _In_ _In_range_(2, 4) size_t waprec, _Out_ LDRColorA& out) + { + InterpolateRGB(c0, c1, wc, wcprec, out); + InterpolateA(c0, c1, wa, waprec, out); + } + }; + + static_assert(sizeof(LDRColorA) == 4, "Unexpected packing"); + + struct LDREndPntPair + { + LDRColorA A; + LDRColorA B; + }; + + inline HDRColorA::HDRColorA(const LDRColorA& c) + { + r = float(c.r) * (1.0f / 255.0f); + g = float(c.g) * (1.0f / 255.0f); + b = float(c.b) * (1.0f / 255.0f); + a = float(c.a) * (1.0f / 255.0f); + } + + inline HDRColorA& HDRColorA::operator = (const LDRColorA& c) + { + r = (float)c.r; + g = (float)c.g; + b = (float)c.b; + a = (float)c.a; + return *this; + } + + inline LDRColorA HDRColorA::ToLDRColorA() const + { + return LDRColorA((uint8_t)(r + 0.01f), (uint8_t)(g + 0.01f), (uint8_t)(b + 0.01f), (uint8_t)(a + 0.01f)); + } +} + +namespace +{ + class INTColor + { + public: + int r, g, b; + int pad; + + public: + INTColor() = default; + INTColor(int nr, int ng, int nb) { r = nr; g = ng; b = nb; } + INTColor(const INTColor& c) { r = c.r; g = c.g; b = c.b; } + + INTColor operator - (_In_ const INTColor& c) const + { + return INTColor(r - c.r, g - c.g, b - c.b); + } + + INTColor& operator += (_In_ const INTColor& c) + { + r += c.r; + g += c.g; + b += c.b; + return *this; + } + + INTColor& operator -= (_In_ const INTColor& c) + { + r -= c.r; + g -= c.g; + b -= c.b; + return *this; + } + + INTColor& operator &= (_In_ const INTColor& c) + { + r &= c.r; + g &= c.g; + b &= c.b; + return *this; + } + + int& operator [] (_In_ uint8_t i) + { + assert(i < sizeof(INTColor) / sizeof(int)); + _Analysis_assume_(i < sizeof(INTColor) / sizeof(int)); + return ((int*) this)[i]; + } + + void Set(_In_ const HDRColorA& c, _In_ bool bSigned) + { + PackedVector::XMHALF4 aF16; + + XMVECTOR v = XMLoadFloat4((const XMFLOAT4*)& c); + XMStoreHalf4(&aF16, v); + + r = F16ToINT(aF16.x, bSigned); + g = F16ToINT(aF16.y, bSigned); + b = F16ToINT(aF16.z, bSigned); + } + + INTColor& Clamp(_In_ int iMin, _In_ int iMax) + { + r = std::min(iMax, std::max(iMin, r)); + g = std::min(iMax, std::max(iMin, g)); + b = std::min(iMax, std::max(iMin, b)); + return *this; + } + + INTColor& SignExtend(_In_ const LDRColorA& Prec) + { + r = SIGN_EXTEND(r, Prec.r); + g = SIGN_EXTEND(g, Prec.g); + b = SIGN_EXTEND(b, Prec.b); + return *this; + } + + void ToF16(_Out_writes_(3) PackedVector::HALF aF16[3], _In_ bool bSigned) const + { + aF16[0] = INT2F16(r, bSigned); + aF16[1] = INT2F16(g, bSigned); + aF16[2] = INT2F16(b, bSigned); + } + + private: + static int F16ToINT(_In_ const PackedVector::HALF& f, _In_ bool bSigned) + { + uint16_t input = *((const uint16_t*)&f); + int out, s; + if (bSigned) + { + s = input & F16S_MASK; + input &= F16EM_MASK; + if (input > F16MAX) out = F16MAX; + else out = input; + out = s ? -out : out; + } + else + { + if (input & F16S_MASK) out = 0; + else out = input; + } + return out; + } + + static PackedVector::HALF INT2F16(_In_ int input, _In_ bool bSigned) + { + PackedVector::HALF h; + uint16_t out; + if (bSigned) + { + int s = 0; + if (input < 0) + { + s = F16S_MASK; + input = -input; + } + out = uint16_t(s | input); + } + else + { + assert(input >= 0 && input <= F16MAX); + out = (uint16_t)input; + } + + *((uint16_t*)&h) = out; + return h; + } + }; + + static_assert(sizeof(INTColor) == 16, "Unexpected packing"); + + struct INTEndPntPair + { + INTColor A; + INTColor B; + }; + + template< size_t SizeInBytes > + class CBits + { + public: + uint8_t GetBit(_Inout_ size_t& uStartBit) const + { + assert(uStartBit < 128); + _Analysis_assume_(uStartBit < 128); + size_t uIndex = uStartBit >> 3; + uint8_t ret = (m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01; + uStartBit++; + return ret; + } + + uint8_t GetBits(_Inout_ size_t& uStartBit, _In_ size_t uNumBits) const + { + if (uNumBits == 0) return 0; + assert(uStartBit + uNumBits <= 128 && uNumBits <= 8); + _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8); + uint8_t ret; + size_t uIndex = uStartBit >> 3; + size_t uBase = uStartBit - (uIndex << 3); + if (uBase + uNumBits > 8) + { + size_t uFirstIndexBits = 8 - uBase; + size_t uNextIndexBits = uNumBits - uFirstIndexBits; + ret = (m_uBits[uIndex] >> uBase) | ((m_uBits[uIndex + 1] & ((1 << uNextIndexBits) - 1)) << uFirstIndexBits); + } + else + { + ret = (m_uBits[uIndex] >> uBase) & ((1 << uNumBits) - 1); + } + assert(ret < (1 << uNumBits)); + uStartBit += uNumBits; + return ret; + } + + void SetBit(_Inout_ size_t& uStartBit, _In_ uint8_t uValue) + { + assert(uStartBit < 128 && uValue < 2); + _Analysis_assume_(uStartBit < 128 && uValue < 2); + size_t uIndex = uStartBit >> 3; + size_t uBase = uStartBit - (uIndex << 3); + m_uBits[uIndex] &= ~(1 << uBase); + m_uBits[uIndex] |= uValue << uBase; + uStartBit++; + } + + void SetBits(_Inout_ size_t& uStartBit, _In_ size_t uNumBits, _In_ uint8_t uValue) + { + if (uNumBits == 0) + return; + assert(uStartBit + uNumBits <= 128 && uNumBits <= 8); + _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8); + assert(uValue < (1 << uNumBits)); + size_t uIndex = uStartBit >> 3; + size_t uBase = uStartBit - (uIndex << 3); + if (uBase + uNumBits > 8) + { + size_t uFirstIndexBits = 8 - uBase; + size_t uNextIndexBits = uNumBits - uFirstIndexBits; + m_uBits[uIndex] &= ~(((1 << uFirstIndexBits) - 1) << uBase); + m_uBits[uIndex] |= uValue << uBase; + m_uBits[uIndex + 1] &= ~((1 << uNextIndexBits) - 1); + m_uBits[uIndex + 1] |= uValue >> uFirstIndexBits; + } + else + { + m_uBits[uIndex] &= ~(((1 << uNumBits) - 1) << uBase); + m_uBits[uIndex] |= uValue << uBase; + } + uStartBit += uNumBits; + } + + private: + uint8_t m_uBits[SizeInBytes]; + }; + + // BC6H compression (16 bits per texel) + class D3DX_BC6H : private CBits< 16 > + { + public: + void Decode(_In_ bool bSigned, _Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const; + void Encode(_In_ bool bSigned, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn); + + private: +#pragma warning(push) +#pragma warning(disable : 4480) + enum EField : uint8_t + { + NA, // N/A + M, // Mode + D, // Shape + RW, + RX, + RY, + RZ, + GW, + GX, + GY, + GZ, + BW, + BX, + BY, + BZ, + }; +#pragma warning(pop) + + struct ModeDescriptor + { + EField m_eField; + uint8_t m_uBit; + }; + + struct ModeInfo + { + uint8_t uMode; + uint8_t uPartitions; + bool bTransformed; + uint8_t uIndexPrec; + LDRColorA RGBAPrec[BC6H_MAX_REGIONS][2]; + }; + +#pragma warning(push) +#pragma warning(disable : 4512) + struct EncodeParams + { + float fBestErr; + const bool bSigned; + uint8_t uMode; + uint8_t uShape; + const HDRColorA* const aHDRPixels; + INTEndPntPair aUnqEndPts[BC6H_MAX_SHAPES][BC6H_MAX_REGIONS]; + INTColor aIPixels[NUM_PIXELS_PER_BLOCK]; + + EncodeParams(const HDRColorA* const aOriginal, bool bSignedFormat) : + fBestErr(FLT_MAX), bSigned(bSignedFormat), aHDRPixels(aOriginal) + { + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + aIPixels[i].Set(aOriginal[i], bSigned); + } + } + }; +#pragma warning(pop) + + static int Quantize(_In_ int iValue, _In_ int prec, _In_ bool bSigned); + static int Unquantize(_In_ int comp, _In_ uint8_t uBitsPerComp, _In_ bool bSigned); + static int FinishUnquantize(_In_ int comp, _In_ bool bSigned); + + static bool EndPointsFit(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[]); + + void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ const INTEndPntPair& endPts, + _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]) const; + float MapColorsQuantized(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ const INTEndPntPair &endPts) const; + float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ uint8_t ch, + _In_ const INTEndPntPair& oldEndPts, _Out_ INTEndPntPair& newEndPts, _In_ float fOldErr, _In_ int do_b) const; + void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ float aOrgErr, + _In_ const INTEndPntPair &aOrgEndPts, _Out_ INTEndPntPair &aOptEndPts) const; + void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const float aOrgErr[], + _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aOrgEndPts[], + _Out_writes_all_(BC6H_MAX_REGIONS) INTEndPntPair aOptEndPts[]) const; + static void SwapIndices(_In_ const EncodeParams* pEP, _Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[], + _In_reads_(NUM_PIXELS_PER_BLOCK) size_t aIndices[]); + void AssignIndices(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[], + _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[], + _Out_writes_(BC6H_MAX_REGIONS) float aTotErr[]) const; + void QuantizeEndPts(_In_ const EncodeParams* pEP, _Out_writes_(BC6H_MAX_REGIONS) INTEndPntPair* qQntEndPts) const; + void EmitBlock(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[], + _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndices[]); + void Refine(_Inout_ EncodeParams* pEP); + + static void GeneratePaletteUnquantized(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]); + float MapColors(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _In_ size_t np, _In_reads_(np) const size_t* auIndex) const; + float RoughMSE(_Inout_ EncodeParams* pEP) const; + + private: + const static ModeDescriptor ms_aDesc[][82]; + const static ModeInfo ms_aInfo[]; + const static int ms_aModeToInfo[]; + }; + + // BC67 compression (16b bits per texel) + class D3DX_BC7 : private CBits< 16 > + { + public: + void Decode(_Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const; + void Encode(DWORD flags, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn); + + private: + struct ModeInfo + { + uint8_t uPartitions; + uint8_t uPartitionBits; + uint8_t uPBits; + uint8_t uRotationBits; + uint8_t uIndexModeBits; + uint8_t uIndexPrec; + uint8_t uIndexPrec2; + LDRColorA RGBAPrec; + LDRColorA RGBAPrecWithP; + }; + +#pragma warning(push) +#pragma warning(disable : 4512) + struct EncodeParams + { + uint8_t uMode; + LDREndPntPair aEndPts[BC7_MAX_SHAPES][BC7_MAX_REGIONS]; + LDRColorA aLDRPixels[NUM_PIXELS_PER_BLOCK]; + const HDRColorA* const aHDRPixels; + + EncodeParams(const HDRColorA* const aOriginal) : aHDRPixels(aOriginal) {} + }; +#pragma warning(pop) + + static uint8_t Quantize(_In_ uint8_t comp, _In_ uint8_t uPrec) + { + assert(0 < uPrec && uPrec <= 8); + uint8_t rnd = (uint8_t)std::min(255, uint16_t(comp) + (1 << (7 - uPrec))); + return rnd >> (8 - uPrec); + } + + static LDRColorA Quantize(_In_ const LDRColorA& c, _In_ const LDRColorA& RGBAPrec) + { + LDRColorA q; + q.r = Quantize(c.r, RGBAPrec.r); + q.g = Quantize(c.g, RGBAPrec.g); + q.b = Quantize(c.b, RGBAPrec.b); + if (RGBAPrec.a) + q.a = Quantize(c.a, RGBAPrec.a); + else + q.a = 255; + return q; + } + + static uint8_t Unquantize(_In_ uint8_t comp, _In_ size_t uPrec) + { + assert(0 < uPrec && uPrec <= 8); + comp = comp << (8 - uPrec); + return comp | (comp >> uPrec); + } + + static LDRColorA Unquantize(_In_ const LDRColorA& c, _In_ const LDRColorA& RGBAPrec) + { + LDRColorA q; + q.r = Unquantize(c.r, RGBAPrec.r); + q.g = Unquantize(c.g, RGBAPrec.g); + q.b = Unquantize(c.b, RGBAPrec.b); + q.a = RGBAPrec.a > 0 ? Unquantize(c.a, RGBAPrec.a) : 255; + return q; + } + + void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ size_t uIndexMode, _In_ const LDREndPntPair& endpts, + _Out_writes_(BC7_MAX_INDICES) LDRColorA aPalette[]) const; + float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode, + _In_ size_t ch, _In_ const LDREndPntPair &old_endpts, + _Out_ LDREndPntPair &new_endpts, _In_ float old_err, _In_ uint8_t do_b) const; + void Exhaustive(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode, + _In_ size_t ch, _Inout_ float& fOrgErr, _Inout_ LDREndPntPair& optEndPt) const; + void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode, + _In_ float orig_err, _In_ const LDREndPntPair &orig_endpts, _Out_ LDREndPntPair &opt_endpts) const; + void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode, + _In_reads_(BC7_MAX_REGIONS) const float orig_err[], + _In_reads_(BC7_MAX_REGIONS) const LDREndPntPair orig_endpts[], + _Out_writes_(BC7_MAX_REGIONS) LDREndPntPair opt_endpts[]) const; + void AssignIndices(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode, + _In_reads_(BC7_MAX_REGIONS) LDREndPntPair endpts[], + _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[], _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices2[], + _Out_writes_(BC7_MAX_REGIONS) float afTotErr[]) const; + void EmitBlock(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode, + _In_reads_(BC7_MAX_REGIONS) const LDREndPntPair aEndPts[], + _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex[], + _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex2[]); + float Refine(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode); + + float MapColors(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode, + _In_ const LDREndPntPair& endPts, _In_ float fMinErr) const; + static float RoughMSE(_Inout_ EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode); + + private: + const static ModeInfo ms_aInfo[]; + }; +} + +// BC6H Compression +const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] = +{ + { // Mode 1 (0x00) - 10 5 5 5 + { M, 0}, { M, 1}, {GY, 4}, {BY, 4}, {BZ, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 2 (0x01) - 7 6 6 6 + { M, 0}, { M, 1}, {GY, 5}, {GZ, 4}, {GZ, 5}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {BZ, 0}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {BY, 5}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BZ, 3}, {BZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RX, 5}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GX, 5}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BX, 5}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {RY, 5}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 3 (0x02) - 11 5 4 4 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RW,10}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GW,10}, + {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BW,10}, + {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 4 (0x06) - 11 4 5 4 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RW,10}, + {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GW,10}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BW,10}, + {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {BZ, 0}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {GY, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 5 (0x0a) - 11 4 4 5 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RW,10}, + {BY, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GW,10}, + {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BW,10}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {BZ, 1}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {BZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 6 (0x0e) - 9 5 5 5 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 7 (0x12) - 8 6 5 5 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {GZ, 4}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BZ, 3}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RX, 5}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {RY, 5}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 8 (0x16) - 8 5 6 5 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {BZ, 0}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GY, 5}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {GZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GX, 5}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 9 (0x1a) - 8 5 5 6 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {BY, 5}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BX, 5}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 10 (0x1e) - 6 6 6 6 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {GZ, 4}, {BZ, 0}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GY, 5}, {BY, 5}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {GZ, 5}, {BZ, 3}, {BZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RX, 5}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GX, 5}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BX, 5}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4}, + {RY, 5}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, { D, 0}, { D, 1}, { D, 2}, + { D, 3}, { D, 4}, + }, + + { // Mode 11 (0x03) - 10 10 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RX, 5}, {RX, 6}, {RX, 7}, {RX, 8}, {RX, 9}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GX, 5}, {GX, 6}, {GX, 7}, {GX, 8}, {GX, 9}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BX, 5}, {BX, 6}, {BX, 7}, {BX, 8}, {BX, 9}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, + }, + + { // Mode 12 (0x07) - 11 9 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RX, 5}, {RX, 6}, {RX, 7}, {RX, 8}, {RW,10}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GX, 5}, {GX, 6}, {GX, 7}, {GX, 8}, {GW,10}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BX, 5}, {BX, 6}, {BX, 7}, {BX, 8}, {BW,10}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, + }, + + { // Mode 13 (0x0b) - 12 8 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4}, + {RX, 5}, {RX, 6}, {RX, 7}, {RW,11}, {RW,10}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4}, + {GX, 5}, {GX, 6}, {GX, 7}, {GW,11}, {GW,10}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4}, + {BX, 5}, {BX, 6}, {BX, 7}, {BW,11}, {BW,10}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, + }, + + { // Mode 14 (0x0f) - 16 4 + { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4}, + {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4}, + {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4}, + {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RW,15}, + {RW,14}, {RW,13}, {RW,12}, {RW,11}, {RW,10}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GW,15}, + {GW,14}, {GW,13}, {GW,12}, {GW,11}, {GW,10}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BW,15}, + {BW,14}, {BW,13}, {BW,12}, {BW,11}, {BW,10}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, + {NA, 0}, {NA, 0}, + }, +}; + +// Mode, Partitions, Transformed, IndexPrec, RGBAPrec +const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[] = +{ + {0x00, 1, true, 3, { { LDRColorA(10,10,10,0), LDRColorA( 5, 5, 5,0) }, { LDRColorA(5,5,5,0), LDRColorA(5,5,5,0) } } }, // Mode 1 + {0x01, 1, true, 3, { { LDRColorA( 7, 7, 7,0), LDRColorA( 6, 6, 6,0) }, { LDRColorA(6,6,6,0), LDRColorA(6,6,6,0) } } }, // Mode 2 + {0x02, 1, true, 3, { { LDRColorA(11,11,11,0), LDRColorA( 5, 4, 4,0) }, { LDRColorA(5,4,4,0), LDRColorA(5,4,4,0) } } }, // Mode 3 + {0x06, 1, true, 3, { { LDRColorA(11,11,11,0), LDRColorA( 4, 5, 4,0) }, { LDRColorA(4,5,4,0), LDRColorA(4,5,4,0) } } }, // Mode 4 + {0x0a, 1, true, 3, { { LDRColorA(11,11,11,0), LDRColorA( 4, 4, 5,0) }, { LDRColorA(4,4,5,0), LDRColorA(4,4,5,0) } } }, // Mode 5 + {0x0e, 1, true, 3, { { LDRColorA( 9, 9, 9,0), LDRColorA( 5, 5, 5,0) }, { LDRColorA(5,5,5,0), LDRColorA(5,5,5,0) } } }, // Mode 6 + {0x12, 1, true, 3, { { LDRColorA( 8, 8, 8,0), LDRColorA( 6, 5, 5,0) }, { LDRColorA(6,5,5,0), LDRColorA(6,5,5,0) } } }, // Mode 7 + {0x16, 1, true, 3, { { LDRColorA( 8, 8, 8,0), LDRColorA( 5, 6, 5,0) }, { LDRColorA(5,6,5,0), LDRColorA(5,6,5,0) } } }, // Mode 8 + {0x1a, 1, true, 3, { { LDRColorA( 8, 8, 8,0), LDRColorA( 5, 5, 6,0) }, { LDRColorA(5,5,6,0), LDRColorA(5,5,6,0) } } }, // Mode 9 + {0x1e, 1, false, 3, { { LDRColorA( 6, 6, 6,0), LDRColorA( 6, 6, 6,0) }, { LDRColorA(6,6,6,0), LDRColorA(6,6,6,0) } } }, // Mode 10 + {0x03, 0, false, 4, { { LDRColorA(10,10,10,0), LDRColorA(10,10,10,0) }, { LDRColorA(0,0,0,0), LDRColorA(0,0,0,0) } } }, // Mode 11 + {0x07, 0, true, 4, { { LDRColorA(11,11,11,0), LDRColorA( 9, 9, 9,0) }, { LDRColorA(0,0,0,0), LDRColorA(0,0,0,0) } } }, // Mode 12 + {0x0b, 0, true, 4, { { LDRColorA(12,12,12,0), LDRColorA( 8, 8, 8,0) }, { LDRColorA(0,0,0,0), LDRColorA(0,0,0,0) } } }, // Mode 13 + {0x0f, 0, true, 4, { { LDRColorA(16,16,16,0), LDRColorA( 4, 4, 4,0) }, { LDRColorA(0,0,0,0), LDRColorA(0,0,0,0) } } }, // Mode 14 +}; + +const int D3DX_BC6H::ms_aModeToInfo[] = +{ + 0, // Mode 1 - 0x00 + 1, // Mode 2 - 0x01 + 2, // Mode 3 - 0x02 + 10, // Mode 11 - 0x03 + -1, // Invalid - 0x04 + -1, // Invalid - 0x05 + 3, // Mode 4 - 0x06 + 11, // Mode 12 - 0x07 + -1, // Invalid - 0x08 + -1, // Invalid - 0x09 + 4, // Mode 5 - 0x0a + 12, // Mode 13 - 0x0b + -1, // Invalid - 0x0c + -1, // Invalid - 0x0d + 5, // Mode 6 - 0x0e + 13, // Mode 14 - 0x0f + -1, // Invalid - 0x10 + -1, // Invalid - 0x11 + 6, // Mode 7 - 0x12 + -1, // Reserved - 0x13 + -1, // Invalid - 0x14 + -1, // Invalid - 0x15 + 7, // Mode 8 - 0x16 + -1, // Reserved - 0x17 + -1, // Invalid - 0x18 + -1, // Invalid - 0x19 + 8, // Mode 9 - 0x1a + -1, // Reserved - 0x1b + -1, // Invalid - 0x1c + -1, // Invalid - 0x1d + 9, // Mode 10 - 0x1e + -1, // Resreved - 0x1f +}; + +// BC7 compression: uPartitions, uPartitionBits, uPBits, uRotationBits, uIndexModeBits, uIndexPrec, uIndexPrec2, RGBAPrec, RGBAPrecWithP +const D3DX_BC7::ModeInfo D3DX_BC7::ms_aInfo[] = +{ + {2, 4, 6, 0, 0, 3, 0, LDRColorA(4,4,4,0), LDRColorA(5,5,5,0)}, + // Mode 0: Color only, 3 Subsets, RGBP 4441 (unique P-bit), 3-bit indecies, 16 partitions + {1, 6, 2, 0, 0, 3, 0, LDRColorA(6,6,6,0), LDRColorA(7,7,7,0)}, + // Mode 1: Color only, 2 Subsets, RGBP 6661 (shared P-bit), 3-bit indecies, 64 partitions + {2, 6, 0, 0, 0, 2, 0, LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, + // Mode 2: Color only, 3 Subsets, RGB 555, 2-bit indecies, 64 partitions + {1, 6, 4, 0, 0, 2, 0, LDRColorA(7,7,7,0), LDRColorA(8,8,8,0)}, + // Mode 3: Color only, 2 Subsets, RGBP 7771 (unique P-bit), 2-bits indecies, 64 partitions + {0, 0, 0, 2, 1, 2, 3, LDRColorA(5,5,5,6), LDRColorA(5,5,5,6)}, + // Mode 4: Color w/ Separate Alpha, 1 Subset, RGB 555, A6, 16x2/16x3-bit indices, 2-bit rotation, 1-bit index selector + {0, 0, 0, 2, 0, 2, 2, LDRColorA(7,7,7,8), LDRColorA(7,7,7,8)}, + // Mode 5: Color w/ Separate Alpha, 1 Subset, RGB 777, A8, 16x2/16x2-bit indices, 2-bit rotation + {0, 0, 2, 0, 0, 4, 0, LDRColorA(7,7,7,7), LDRColorA(8,8,8,8)}, + // Mode 6: Color+Alpha, 1 Subset, RGBAP 77771 (unique P-bit), 16x4-bit indecies + {1, 6, 4, 0, 0, 2, 0, LDRColorA(5,5,5,5), LDRColorA(6,6,6,6)} + // Mode 7: Color+Alpha, 2 Subsets, RGBAP 55551 (unique P-bit), 2-bit indices, 64 partitions +}; + + +namespace +{ + //------------------------------------------------------------------------------------- + // Helper functions + //------------------------------------------------------------------------------------- + inline bool IsFixUpOffset(_In_range_(0, 2) size_t uPartitions, _In_range_(0, 63) size_t uShape, _In_range_(0, 15) size_t uOffset) + { + assert(uPartitions < 3 && uShape < 64 && uOffset < 16); + _Analysis_assume_(uPartitions < 3 && uShape < 64 && uOffset < 16); + for (size_t p = 0; p <= uPartitions; p++) + { + if (uOffset == g_aFixUp[uPartitions][uShape][p]) + { + return true; + } + } + return false; + } + + inline void TransformForward(_Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[]) + { + aEndPts[0].B -= aEndPts[0].A; + aEndPts[1].A -= aEndPts[0].A; + aEndPts[1].B -= aEndPts[0].A; + } + + inline void TransformInverse(_Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[], _In_ const LDRColorA& Prec, _In_ bool bSigned) + { + INTColor WrapMask((1 << Prec.r) - 1, (1 << Prec.g) - 1, (1 << Prec.b) - 1); + aEndPts[0].B += aEndPts[0].A; aEndPts[0].B &= WrapMask; + aEndPts[1].A += aEndPts[0].A; aEndPts[1].A &= WrapMask; + aEndPts[1].B += aEndPts[0].A; aEndPts[1].B &= WrapMask; + if (bSigned) + { + aEndPts[0].B.SignExtend(Prec); + aEndPts[1].A.SignExtend(Prec); + aEndPts[1].B.SignExtend(Prec); + } + } + + inline float Norm(_In_ const INTColor& a, _In_ const INTColor& b) + { + float dr = float(a.r) - float(b.r); + float dg = float(a.g) - float(b.g); + float db = float(a.b) - float(b.b); + return dr * dr + dg * dg + db * db; + } + + // return # of bits needed to store n. handle signed or unsigned cases properly + inline int NBits(_In_ int n, _In_ bool bIsSigned) + { + int nb; + if (n == 0) + { + return 0; // no bits needed for 0, signed or not + } + else if (n > 0) + { + for (nb = 0; n; ++nb, n >>= 1); + return nb + (bIsSigned ? 1 : 0); + } + else + { + assert(bIsSigned); + for (nb = 0; n < -1; ++nb, n >>= 1); + return nb + 1; + } + } + + + //------------------------------------------------------------------------------------- + float OptimizeRGB( + _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints, + _Out_ HDRColorA* pX, + _Out_ HDRColorA* pY, + _In_range_(3, 4) size_t cSteps, + size_t cPixels, + _In_reads_(cPixels) const size_t* pIndex) + { + float fError = FLT_MAX; + const float *pC = (3 == cSteps) ? pC3 : pC4; + const float *pD = (3 == cSteps) ? pD3 : pD4; + + // Find Min and Max points, as starting point + HDRColorA X(1.0f, 1.0f, 1.0f, 0.0f); + HDRColorA Y(0.0f, 0.0f, 0.0f, 0.0f); + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + if (pPoints[pIndex[iPoint]].r < X.r) X.r = pPoints[pIndex[iPoint]].r; + if (pPoints[pIndex[iPoint]].g < X.g) X.g = pPoints[pIndex[iPoint]].g; + if (pPoints[pIndex[iPoint]].b < X.b) X.b = pPoints[pIndex[iPoint]].b; + if (pPoints[pIndex[iPoint]].r > Y.r) Y.r = pPoints[pIndex[iPoint]].r; + if (pPoints[pIndex[iPoint]].g > Y.g) Y.g = pPoints[pIndex[iPoint]].g; + if (pPoints[pIndex[iPoint]].b > Y.b) Y.b = pPoints[pIndex[iPoint]].b; + } + + // Diagonal axis + HDRColorA AB; + AB.r = Y.r - X.r; + AB.g = Y.g - X.g; + AB.b = Y.b - X.b; + + float fAB = AB.r * AB.r + AB.g * AB.g + AB.b * AB.b; + + // Single color block.. no need to root-find + if (fAB < FLT_MIN) + { + pX->r = X.r; pX->g = X.g; pX->b = X.b; + pY->r = Y.r; pY->g = Y.g; pY->b = Y.b; + return 0.0f; + } + + // Try all four axis directions, to determine which diagonal best fits data + float fABInv = 1.0f / fAB; + + HDRColorA Dir; + Dir.r = AB.r * fABInv; + Dir.g = AB.g * fABInv; + Dir.b = AB.b * fABInv; + + HDRColorA Mid; + Mid.r = (X.r + Y.r) * 0.5f; + Mid.g = (X.g + Y.g) * 0.5f; + Mid.b = (X.b + Y.b) * 0.5f; + + float fDir[4]; + fDir[0] = fDir[1] = fDir[2] = fDir[3] = 0.0f; + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + HDRColorA Pt; + Pt.r = (pPoints[pIndex[iPoint]].r - Mid.r) * Dir.r; + Pt.g = (pPoints[pIndex[iPoint]].g - Mid.g) * Dir.g; + Pt.b = (pPoints[pIndex[iPoint]].b - Mid.b) * Dir.b; + + float f; + f = Pt.r + Pt.g + Pt.b; fDir[0] += f * f; + f = Pt.r + Pt.g - Pt.b; fDir[1] += f * f; + f = Pt.r - Pt.g + Pt.b; fDir[2] += f * f; + f = Pt.r - Pt.g - Pt.b; fDir[3] += f * f; + } + + float fDirMax = fDir[0]; + size_t iDirMax = 0; + + for (size_t iDir = 1; iDir < 4; iDir++) + { + if (fDir[iDir] > fDirMax) + { + fDirMax = fDir[iDir]; + iDirMax = iDir; + } + } + + if (iDirMax & 2) std::swap(X.g, Y.g); + if (iDirMax & 1) std::swap(X.b, Y.b); + + // Two color block.. no need to root-find + if (fAB < 1.0f / 4096.0f) + { + pX->r = X.r; pX->g = X.g; pX->b = X.b; + pY->r = Y.r; pY->g = Y.g; pY->b = Y.b; + return 0.0f; + } + + // Use Newton's Method to find local minima of sum-of-squares error. + float fSteps = (float)(cSteps - 1); + + for (size_t iIteration = 0; iIteration < 8; iIteration++) + { + // Calculate new steps + HDRColorA pSteps[4] = {}; + + for (size_t iStep = 0; iStep < cSteps; iStep++) + { + pSteps[iStep].r = X.r * pC[iStep] + Y.r * pD[iStep]; + pSteps[iStep].g = X.g * pC[iStep] + Y.g * pD[iStep]; + pSteps[iStep].b = X.b * pC[iStep] + Y.b * pD[iStep]; + } + + // Calculate color direction + Dir.r = Y.r - X.r; + Dir.g = Y.g - X.g; + Dir.b = Y.b - X.b; + + float fLen = (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b); + + if (fLen < (1.0f / 4096.0f)) + break; + + float fScale = fSteps / fLen; + + Dir.r *= fScale; + Dir.g *= fScale; + Dir.b *= fScale; + + // Evaluate function, and derivatives + float d2X = 0.0f, d2Y = 0.0f; + HDRColorA dX(0.0f, 0.0f, 0.0f, 0.0f), dY(0.0f, 0.0f, 0.0f, 0.0f); + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + float fDot = (pPoints[pIndex[iPoint]].r - X.r) * Dir.r + + (pPoints[pIndex[iPoint]].g - X.g) * Dir.g + + (pPoints[pIndex[iPoint]].b - X.b) * Dir.b; + + size_t iStep; + if (fDot <= 0.0f) + iStep = 0; + if (fDot >= fSteps) + iStep = cSteps - 1; + else + iStep = size_t(fDot + 0.5f); + + HDRColorA Diff; + Diff.r = pSteps[iStep].r - pPoints[pIndex[iPoint]].r; + Diff.g = pSteps[iStep].g - pPoints[pIndex[iPoint]].g; + Diff.b = pSteps[iStep].b - pPoints[pIndex[iPoint]].b; + + float fC = pC[iStep] * (1.0f / 8.0f); + float fD = pD[iStep] * (1.0f / 8.0f); + + d2X += fC * pC[iStep]; + dX.r += fC * Diff.r; + dX.g += fC * Diff.g; + dX.b += fC * Diff.b; + + d2Y += fD * pD[iStep]; + dY.r += fD * Diff.r; + dY.g += fD * Diff.g; + dY.b += fD * Diff.b; + } + + // Move endpoints + if (d2X > 0.0f) + { + float f = -1.0f / d2X; + + X.r += dX.r * f; + X.g += dX.g * f; + X.b += dX.b * f; + } + + if (d2Y > 0.0f) + { + float f = -1.0f / d2Y; + + Y.r += dY.r * f; + Y.g += dY.g * f; + Y.b += dY.b * f; + } + + if ((dX.r * dX.r < fEpsilon) && (dX.g * dX.g < fEpsilon) && (dX.b * dX.b < fEpsilon) && + (dY.r * dY.r < fEpsilon) && (dY.g * dY.g < fEpsilon) && (dY.b * dY.b < fEpsilon)) + { + break; + } + } + + pX->r = X.r; pX->g = X.g; pX->b = X.b; + pY->r = Y.r; pY->g = Y.g; pY->b = Y.b; + return fError; + } + + + //------------------------------------------------------------------------------------- + float OptimizeRGBA( + _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints, + _Out_ HDRColorA* pX, + _Out_ HDRColorA* pY, + _In_range_(3, 4) size_t cSteps, + size_t cPixels, + _In_reads_(cPixels) const size_t* pIndex) + { + float fError = FLT_MAX; + const float *pC = (3 == cSteps) ? pC3 : pC4; + const float *pD = (3 == cSteps) ? pD3 : pD4; + + // Find Min and Max points, as starting point + HDRColorA X(1.0f, 1.0f, 1.0f, 1.0f); + HDRColorA Y(0.0f, 0.0f, 0.0f, 0.0f); + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + if (pPoints[pIndex[iPoint]].r < X.r) X.r = pPoints[pIndex[iPoint]].r; + if (pPoints[pIndex[iPoint]].g < X.g) X.g = pPoints[pIndex[iPoint]].g; + if (pPoints[pIndex[iPoint]].b < X.b) X.b = pPoints[pIndex[iPoint]].b; + if (pPoints[pIndex[iPoint]].a < X.a) X.a = pPoints[pIndex[iPoint]].a; + if (pPoints[pIndex[iPoint]].r > Y.r) Y.r = pPoints[pIndex[iPoint]].r; + if (pPoints[pIndex[iPoint]].g > Y.g) Y.g = pPoints[pIndex[iPoint]].g; + if (pPoints[pIndex[iPoint]].b > Y.b) Y.b = pPoints[pIndex[iPoint]].b; + if (pPoints[pIndex[iPoint]].a > Y.a) Y.a = pPoints[pIndex[iPoint]].a; + } + + // Diagonal axis + HDRColorA AB = Y - X; + float fAB = AB * AB; + + // Single color block.. no need to root-find + if (fAB < FLT_MIN) + { + *pX = X; + *pY = Y; + return 0.0f; + } + + // Try all four axis directions, to determine which diagonal best fits data + float fABInv = 1.0f / fAB; + HDRColorA Dir = AB * fABInv; + HDRColorA Mid = (X + Y) * 0.5f; + + float fDir[8]; + fDir[0] = fDir[1] = fDir[2] = fDir[3] = fDir[4] = fDir[5] = fDir[6] = fDir[7] = 0.0f; + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + HDRColorA Pt; + Pt.r = (pPoints[pIndex[iPoint]].r - Mid.r) * Dir.r; + Pt.g = (pPoints[pIndex[iPoint]].g - Mid.g) * Dir.g; + Pt.b = (pPoints[pIndex[iPoint]].b - Mid.b) * Dir.b; + Pt.a = (pPoints[pIndex[iPoint]].a - Mid.a) * Dir.a; + + float f; + f = Pt.r + Pt.g + Pt.b + Pt.a; fDir[0] += f * f; + f = Pt.r + Pt.g + Pt.b - Pt.a; fDir[1] += f * f; + f = Pt.r + Pt.g - Pt.b + Pt.a; fDir[2] += f * f; + f = Pt.r + Pt.g - Pt.b - Pt.a; fDir[3] += f * f; + f = Pt.r - Pt.g + Pt.b + Pt.a; fDir[4] += f * f; + f = Pt.r - Pt.g + Pt.b - Pt.a; fDir[5] += f * f; + f = Pt.r - Pt.g - Pt.b + Pt.a; fDir[6] += f * f; + f = Pt.r - Pt.g - Pt.b - Pt.a; fDir[7] += f * f; + } + + float fDirMax = fDir[0]; + size_t iDirMax = 0; + + for (size_t iDir = 1; iDir < 8; iDir++) + { + if (fDir[iDir] > fDirMax) + { + fDirMax = fDir[iDir]; + iDirMax = iDir; + } + } + + if (iDirMax & 4) std::swap(X.g, Y.g); + if (iDirMax & 2) std::swap(X.b, Y.b); + if (iDirMax & 1) std::swap(X.a, Y.a); + + // Two color block.. no need to root-find + if (fAB < 1.0f / 4096.0f) + { + *pX = X; + *pY = Y; + return 0.0f; + } + + // Use Newton's Method to find local minima of sum-of-squares error. + float fSteps = (float)(cSteps - 1); + + for (size_t iIteration = 0; iIteration < 8 && fError > 0.0f; iIteration++) + { + // Calculate new steps + HDRColorA pSteps[BC7_MAX_INDICES]; + + LDRColorA lX, lY; + lX = (X * 255.0f).ToLDRColorA(); + lY = (Y * 255.0f).ToLDRColorA(); + + for (size_t iStep = 0; iStep < cSteps; iStep++) + { + pSteps[iStep] = X * pC[iStep] + Y * pD[iStep]; + //LDRColorA::Interpolate(lX, lY, i, i, wcprec, waprec, aSteps[i]); + } + + // Calculate color direction + Dir = Y - X; + float fLen = Dir * Dir; + if (fLen < (1.0f / 4096.0f)) + break; + + float fScale = fSteps / fLen; + Dir *= fScale; + + // Evaluate function, and derivatives + float d2X = 0.0f, d2Y = 0.0f; + HDRColorA dX(0.0f, 0.0f, 0.0f, 0.0f), dY(0.0f, 0.0f, 0.0f, 0.0f); + + for (size_t iPoint = 0; iPoint < cPixels; ++iPoint) + { + float fDot = (pPoints[pIndex[iPoint]] - X) * Dir; + size_t iStep; + if (fDot <= 0.0f) + iStep = 0; + if (fDot >= fSteps) + iStep = cSteps - 1; + else + iStep = size_t(fDot + 0.5f); + + HDRColorA Diff = pSteps[iStep] - pPoints[pIndex[iPoint]]; + float fC = pC[iStep] * (1.0f / 8.0f); + float fD = pD[iStep] * (1.0f / 8.0f); + + d2X += fC * pC[iStep]; + dX += Diff * fC; + + d2Y += fD * pD[iStep]; + dY += Diff * fD; + } + + // Move endpoints + if (d2X > 0.0f) + { + float f = -1.0f / d2X; + X += dX * f; + } + + if (d2Y > 0.0f) + { + float f = -1.0f / d2Y; + Y += dY * f; + } + + if ((dX * dX < fEpsilon) && (dY * dY < fEpsilon)) + break; + } + + *pX = X; + *pY = Y; + return fError; + } + + + //------------------------------------------------------------------------------------- + float ComputeError( + _Inout_ const LDRColorA& pixel, + _In_reads_(1 << uIndexPrec) const LDRColorA aPalette[], + uint8_t uIndexPrec, + uint8_t uIndexPrec2, + _Out_opt_ size_t* pBestIndex = nullptr, + _Out_opt_ size_t* pBestIndex2 = nullptr) + { + const size_t uNumIndices = size_t(1) << uIndexPrec; + const size_t uNumIndices2 = size_t(1) << uIndexPrec2; + float fTotalErr = 0; + float fBestErr = FLT_MAX; + + if (pBestIndex) + *pBestIndex = 0; + if (pBestIndex2) + *pBestIndex2 = 0; + + XMVECTOR vpixel = XMLoadUByte4(reinterpret_cast(&pixel)); + + if (uIndexPrec2 == 0) + { + for (size_t i = 0; i < uNumIndices && fBestErr > 0; i++) + { + XMVECTOR tpixel = XMLoadUByte4(reinterpret_cast(&aPalette[i])); + // Compute ErrorMetric + tpixel = XMVectorSubtract(vpixel, tpixel); + float fErr = XMVectorGetX(XMVector4Dot(tpixel, tpixel)); + if (fErr > fBestErr) // error increased, so we're done searching + break; + if (fErr < fBestErr) + { + fBestErr = fErr; + if (pBestIndex) + *pBestIndex = i; + } + } + fTotalErr += fBestErr; + } + else + { + for (size_t i = 0; i < uNumIndices && fBestErr > 0; i++) + { + XMVECTOR tpixel = XMLoadUByte4(reinterpret_cast(&aPalette[i])); + // Compute ErrorMetricRGB + tpixel = XMVectorSubtract(vpixel, tpixel); + float fErr = XMVectorGetX(XMVector3Dot(tpixel, tpixel)); + if (fErr > fBestErr) // error increased, so we're done searching + break; + if (fErr < fBestErr) + { + fBestErr = fErr; + if (pBestIndex) + *pBestIndex = i; + } + } + fTotalErr += fBestErr; + fBestErr = FLT_MAX; + for (size_t i = 0; i < uNumIndices2 && fBestErr > 0; i++) + { + // Compute ErrorMetricAlpha + float ea = float(pixel.a) - float(aPalette[i].a); + float fErr = ea*ea; + if (fErr > fBestErr) // error increased, so we're done searching + break; + if (fErr < fBestErr) + { + fBestErr = fErr; + if (pBestIndex2) + *pBestIndex2 = i; + } + } + fTotalErr += fBestErr; + } + + return fTotalErr; + } + + + void FillWithErrorColors(_Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) + { + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { +#ifdef _DEBUG + // Use Magenta in debug as a highly-visible error color + pOut[i] = HDRColorA(1.0f, 0.0f, 1.0f, 1.0f); +#else + // In production use, default to black + pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); +#endif + } + } +} + + +//------------------------------------------------------------------------------------- +// BC6H Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const +{ + assert(pOut); + + size_t uStartBit = 0; + uint8_t uMode = GetBits(uStartBit, 2); + if (uMode != 0x00 && uMode != 0x01) + { + uMode = (GetBits(uStartBit, 3) << 2) | uMode; + } + + assert(uMode < 32); + _Analysis_assume_(uMode < 32); + + if (ms_aModeToInfo[uMode] >= 0) + { + assert(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo)); + _Analysis_assume_(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo)); + const ModeDescriptor* desc = ms_aDesc[ms_aModeToInfo[uMode]]; + + assert(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc)); + _Analysis_assume_(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc)); + const ModeInfo& info = ms_aInfo[ms_aModeToInfo[uMode]]; + + INTEndPntPair aEndPts[BC6H_MAX_REGIONS]; + memset(aEndPts, 0, BC6H_MAX_REGIONS * 2 * sizeof(INTColor)); + uint32_t uShape = 0; + + // Read header + const size_t uHeaderBits = info.uPartitions > 0 ? 82 : 65; + while (uStartBit < uHeaderBits) + { + size_t uCurBit = uStartBit; + if (GetBit(uStartBit)) + { + switch (desc[uCurBit].m_eField) + { + case D: uShape |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RW: aEndPts[0].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RX: aEndPts[0].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RY: aEndPts[1].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RZ: aEndPts[1].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GW: aEndPts[0].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GX: aEndPts[0].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GY: aEndPts[1].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GZ: aEndPts[1].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BW: aEndPts[0].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BX: aEndPts[0].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BY: aEndPts[1].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BZ: aEndPts[1].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + default: + { +#ifdef _DEBUG + OutputDebugStringA("BC6H: Invalid header bits encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + } + } + } + + assert(uShape < 64); + _Analysis_assume_(uShape < 64); + + // Sign extend necessary end points + if (bSigned) + { + aEndPts[0].A.SignExtend(info.RGBAPrec[0][0]); + } + if (bSigned || info.bTransformed) + { + assert(info.uPartitions < BC6H_MAX_REGIONS); + _Analysis_assume_(info.uPartitions < BC6H_MAX_REGIONS); + for (size_t p = 0; p <= info.uPartitions; ++p) + { + if (p != 0) + { + aEndPts[p].A.SignExtend(info.RGBAPrec[p][0]); + } + aEndPts[p].B.SignExtend(info.RGBAPrec[p][1]); + } + } + + // Inverse transform the end points + if (info.bTransformed) + { + TransformInverse(aEndPts, info.RGBAPrec[0][0], bSigned); + } + + // Read indices + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + size_t uNumBits = IsFixUpOffset(info.uPartitions, uShape, i) ? info.uIndexPrec - 1 : info.uIndexPrec; + if (uStartBit + uNumBits > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC6H: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + uint8_t uIndex = GetBits(uStartBit, uNumBits); + + if (uIndex >= ((info.uPartitions > 0) ? 8 : 16)) + { +#ifdef _DEBUG + OutputDebugStringA("BC6H: Invalid index encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + size_t uRegion = g_aPartitionTable[info.uPartitions][uShape][i]; + assert(uRegion < BC6H_MAX_REGIONS); + _Analysis_assume_(uRegion < BC6H_MAX_REGIONS); + + // Unquantize endpoints and interpolate + int r1 = Unquantize(aEndPts[uRegion].A.r, info.RGBAPrec[0][0].r, bSigned); + int g1 = Unquantize(aEndPts[uRegion].A.g, info.RGBAPrec[0][0].g, bSigned); + int b1 = Unquantize(aEndPts[uRegion].A.b, info.RGBAPrec[0][0].b, bSigned); + int r2 = Unquantize(aEndPts[uRegion].B.r, info.RGBAPrec[0][0].r, bSigned); + int g2 = Unquantize(aEndPts[uRegion].B.g, info.RGBAPrec[0][0].g, bSigned); + int b2 = Unquantize(aEndPts[uRegion].B.b, info.RGBAPrec[0][0].b, bSigned); + const int* aWeights = info.uPartitions > 0 ? g_aWeights3 : g_aWeights4; + INTColor fc; + fc.r = FinishUnquantize((r1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + r2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + fc.g = FinishUnquantize((g1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + g2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + fc.b = FinishUnquantize((b1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + b2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned); + + HALF rgb[3]; + fc.ToF16(rgb, bSigned); + + pOut[i].r = XMConvertHalfToFloat(rgb[0]); + pOut[i].g = XMConvertHalfToFloat(rgb[1]); + pOut[i].b = XMConvertHalfToFloat(rgb[2]); + pOut[i].a = 1.0f; + } + } + else + { +#ifdef _DEBUG + const char* warnstr = "BC6H: Invalid mode encountered during decoding\n"; + switch (uMode) + { + case 0x13: warnstr = "BC6H: Reserved mode 10011 encountered during decoding\n"; break; + case 0x17: warnstr = "BC6H: Reserved mode 10111 encountered during decoding\n"; break; + case 0x1B: warnstr = "BC6H: Reserved mode 11011 encountered during decoding\n"; break; + case 0x1F: warnstr = "BC6H: Reserved mode 11111 encountered during decoding\n"; break; + } + OutputDebugStringA(warnstr); +#endif + // Per the BC6H format spec, we must return opaque black + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); + } + } +} + + +_Use_decl_annotations_ +void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn) +{ + assert(pIn); + + EncodeParams EP(pIn, bSigned); + + for (EP.uMode = 0; EP.uMode < ARRAYSIZE(ms_aInfo) && EP.fBestErr > 0; ++EP.uMode) + { + const uint8_t uShapes = ms_aInfo[EP.uMode].uPartitions ? 32 : 1; + // Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes + // uShapes/4 gets nearly all the cases; you can increase that a bit (say by 3 or 4) if you really want to squeeze the last bit out + const size_t uItems = std::max(1, uShapes >> 2); + float afRoughMSE[BC6H_MAX_SHAPES]; + uint8_t auShape[BC6H_MAX_SHAPES]; + + // pick the best uItems shapes and refine these. + for (EP.uShape = 0; EP.uShape < uShapes; ++EP.uShape) + { + size_t uShape = EP.uShape; + afRoughMSE[uShape] = RoughMSE(&EP); + auShape[uShape] = static_cast(uShape); + } + + // Bubble up the first uItems items + for (size_t i = 0; i < uItems; i++) + { + for (size_t j = i + 1; j < uShapes; j++) + { + if (afRoughMSE[i] > afRoughMSE[j]) + { + std::swap(afRoughMSE[i], afRoughMSE[j]); + std::swap(auShape[i], auShape[j]); + } + } + } + + for (size_t i = 0; i < uItems && EP.fBestErr > 0; i++) + { + EP.uShape = auShape[i]; + Refine(&EP); + } + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +int D3DX_BC6H::Quantize(int iValue, int prec, bool bSigned) +{ + assert(prec > 1); // didn't bother to make it work for 1 + int q, s = 0; + if (bSigned) + { + assert(iValue >= -F16MAX && iValue <= F16MAX); + if (iValue < 0) + { + s = 1; + iValue = -iValue; + } + q = (prec >= 16) ? iValue : (iValue << (prec - 1)) / (F16MAX + 1); + if (s) + q = -q; + assert(q > -(1 << (prec - 1)) && q < (1 << (prec - 1))); + } + else + { + assert(iValue >= 0 && iValue <= F16MAX); + q = (prec >= 15) ? iValue : (iValue << prec) / (F16MAX + 1); + assert(q >= 0 && q < (1 << prec)); + } + + return q; +} + + +_Use_decl_annotations_ +int D3DX_BC6H::Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned) +{ + int unq = 0, s = 0; + if (bSigned) + { + if (uBitsPerComp >= 16) + { + unq = comp; + } + else + { + if (comp < 0) + { + s = 1; + comp = -comp; + } + + if (comp == 0) unq = 0; + else if (comp >= ((1 << (uBitsPerComp - 1)) - 1)) unq = 0x7FFF; + else unq = ((comp << 15) + 0x4000) >> (uBitsPerComp - 1); + + if (s) unq = -unq; + } + } + else + { + if (uBitsPerComp >= 15) unq = comp; + else if (comp == 0) unq = 0; + else if (comp == ((1 << uBitsPerComp) - 1)) unq = 0xFFFF; + else unq = ((comp << 16) + 0x8000) >> uBitsPerComp; + } + + return unq; +} + + +_Use_decl_annotations_ +int D3DX_BC6H::FinishUnquantize(int comp, bool bSigned) +{ + if (bSigned) + { + return (comp < 0) ? -(((-comp) * 31) >> 5) : (comp * 31) >> 5; // scale the magnitude by 31/32 + } + else + { + return (comp * 31) >> 6; // scale the magnitude by 31/64 + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool D3DX_BC6H::EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPts[]) +{ + assert(pEP); + const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed; + const bool bIsSigned = pEP->bSigned; + const LDRColorA& Prec0 = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; + const LDRColorA& Prec1 = ms_aInfo[pEP->uMode].RGBAPrec[0][1]; + const LDRColorA& Prec2 = ms_aInfo[pEP->uMode].RGBAPrec[1][0]; + const LDRColorA& Prec3 = ms_aInfo[pEP->uMode].RGBAPrec[1][1]; + + INTColor aBits[4]; + aBits[0].r = NBits(aEndPts[0].A.r, bIsSigned); + aBits[0].g = NBits(aEndPts[0].A.g, bIsSigned); + aBits[0].b = NBits(aEndPts[0].A.b, bIsSigned); + aBits[1].r = NBits(aEndPts[0].B.r, bTransformed || bIsSigned); + aBits[1].g = NBits(aEndPts[0].B.g, bTransformed || bIsSigned); + aBits[1].b = NBits(aEndPts[0].B.b, bTransformed || bIsSigned); + if (aBits[0].r > Prec0.r || aBits[1].r > Prec1.r || + aBits[0].g > Prec0.g || aBits[1].g > Prec1.g || + aBits[0].b > Prec0.b || aBits[1].b > Prec1.b) + return false; + + if (ms_aInfo[pEP->uMode].uPartitions) + { + aBits[2].r = NBits(aEndPts[1].A.r, bTransformed || bIsSigned); + aBits[2].g = NBits(aEndPts[1].A.g, bTransformed || bIsSigned); + aBits[2].b = NBits(aEndPts[1].A.b, bTransformed || bIsSigned); + aBits[3].r = NBits(aEndPts[1].B.r, bTransformed || bIsSigned); + aBits[3].g = NBits(aEndPts[1].B.g, bTransformed || bIsSigned); + aBits[3].b = NBits(aEndPts[1].B.b, bTransformed || bIsSigned); + + if (aBits[2].r > Prec2.r || aBits[3].r > Prec3.r || + aBits[2].g > Prec2.g || aBits[3].g > Prec3.g || + aBits[2].b > Prec2.b || aBits[3].b > Prec3.b) + return false; + } + + return true; +} + + +_Use_decl_annotations_ +void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPntPair& endPts, INTColor aPalette[]) const +{ + assert(pEP); + const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uNumIndices = size_t(1) << uIndexPrec; + assert(uNumIndices > 0); + _Analysis_assume_(uNumIndices > 0); + const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; + + // scale endpoints + INTEndPntPair unqEndPts; + unqEndPts.A.r = Unquantize(endPts.A.r, Prec.r, pEP->bSigned); + unqEndPts.A.g = Unquantize(endPts.A.g, Prec.g, pEP->bSigned); + unqEndPts.A.b = Unquantize(endPts.A.b, Prec.b, pEP->bSigned); + unqEndPts.B.r = Unquantize(endPts.B.r, Prec.r, pEP->bSigned); + unqEndPts.B.g = Unquantize(endPts.B.g, Prec.g, pEP->bSigned); + unqEndPts.B.b = Unquantize(endPts.B.b, Prec.b, pEP->bSigned); + + // interpolate + const int* aWeights = nullptr; + switch (uIndexPrec) + { + case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); _Analysis_assume_(uNumIndices <= 8); break; + case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); _Analysis_assume_(uNumIndices <= 16); break; + default: + assert(false); + for (size_t i = 0; i < uNumIndices; ++i) + { +#pragma prefast(suppress:22102 22103, "writing blocks in two halves confuses tool") + aPalette[i] = INTColor(0, 0, 0); + } + return; + } + + for (size_t i = 0; i < uNumIndices; ++i) + { + aPalette[i].r = FinishUnquantize( + (unqEndPts.A.r * (BC67_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.r * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, + pEP->bSigned); + aPalette[i].g = FinishUnquantize( + (unqEndPts.A.g * (BC67_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.g * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, + pEP->bSigned); + aPalette[i].b = FinishUnquantize( + (unqEndPts.A.b * (BC67_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.b * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, + pEP->bSigned); + } +} + + +// given a collection of colors and quantized endpoints, generate a palette, choose best entries, and return a single toterr +_Use_decl_annotations_ +float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aColors[], size_t np, const INTEndPntPair &endPts) const +{ + assert(pEP); + + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const uint8_t uNumIndices = 1 << uIndexPrec; + INTColor aPalette[BC6H_MAX_INDICES]; + GeneratePaletteQuantized(pEP, endPts, aPalette); + + float fTotErr = 0; + for (size_t i = 0; i < np; ++i) + { + XMVECTOR vcolors = XMLoadSInt4(reinterpret_cast(&aColors[i])); + + // Compute ErrorMetricRGB + XMVECTOR tpal = XMLoadSInt4(reinterpret_cast(&aPalette[0])); + tpal = XMVectorSubtract(vcolors, tpal); + float fBestErr = XMVectorGetX(XMVector3Dot(tpal, tpal)); + + for (int j = 1; j < uNumIndices && fBestErr > 0; ++j) + { + // Compute ErrorMetricRGB + tpal = XMLoadSInt4(reinterpret_cast(&aPalette[j])); + tpal = XMVectorSubtract(vcolors, tpal); + float fErr = XMVectorGetX(XMVector3Dot(tpal, tpal)); + if (fErr > fBestErr) break; // error increased, so we're done searching + if (fErr < fBestErr) fBestErr = fErr; + } + fTotErr += fBestErr; + } + return fTotErr; +} + + +_Use_decl_annotations_ +float D3DX_BC6H::PerturbOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, uint8_t ch, + const INTEndPntPair& oldEndPts, INTEndPntPair& newEndPts, float fOldErr, int do_b) const +{ + assert(pEP); + uint8_t uPrec; + switch (ch) + { + case 0: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].r; break; + case 1: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].g; break; + case 2: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].b; break; + default: assert(false); newEndPts = oldEndPts; return FLT_MAX; + } + INTEndPntPair tmpEndPts; + float fMinErr = fOldErr; + int beststep = 0; + + // copy real endpoints so we can perturb them + tmpEndPts = newEndPts = oldEndPts; + + // do a logarithmic search for the best error for this endpoint (which) + for (int step = 1 << (uPrec - 1); step; step >>= 1) + { + bool bImproved = false; + for (int sign = -1; sign <= 1; sign += 2) + { + if (do_b == 0) + { + tmpEndPts.A[ch] = newEndPts.A[ch] + sign * step; + if (tmpEndPts.A[ch] < 0 || tmpEndPts.A[ch] >= (1 << uPrec)) + continue; + } + else + { + tmpEndPts.B[ch] = newEndPts.B[ch] + sign * step; + if (tmpEndPts.B[ch] < 0 || tmpEndPts.B[ch] >= (1 << uPrec)) + continue; + } + + float fErr = MapColorsQuantized(pEP, aColors, np, tmpEndPts); + + if (fErr < fMinErr) + { + bImproved = true; + fMinErr = fErr; + beststep = sign * step; + } + } + // if this was an improvement, move the endpoint and continue search from there + if (bImproved) + { + if (do_b == 0) + newEndPts.A[ch] += beststep; + else + newEndPts.B[ch] += beststep; + } + } + return fMinErr; +} + + +_Use_decl_annotations_ +void D3DX_BC6H::OptimizeOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, float aOrgErr, + const INTEndPntPair &aOrgEndPts, INTEndPntPair &aOptEndPts) const +{ + assert(pEP); + float aOptErr = aOrgErr; + aOptEndPts.A = aOrgEndPts.A; + aOptEndPts.B = aOrgEndPts.B; + + INTEndPntPair new_a, new_b; + INTEndPntPair newEndPts; + int do_b; + + // now optimize each channel separately + for (uint8_t ch = 0; ch < 3; ++ch) + { + // figure out which endpoint when perturbed gives the most improvement and start there + // if we just alternate, we can easily end up in a local minima + float fErr0 = PerturbOne(pEP, aColors, np, ch, aOptEndPts, new_a, aOptErr, 0); // perturb endpt A + float fErr1 = PerturbOne(pEP, aColors, np, ch, aOptEndPts, new_b, aOptErr, 1); // perturb endpt B + + if (fErr0 < fErr1) + { + if (fErr0 >= aOptErr) continue; + aOptEndPts.A[ch] = new_a.A[ch]; + aOptErr = fErr0; + do_b = 1; // do B next + } + else + { + if (fErr1 >= aOptErr) continue; + aOptEndPts.B[ch] = new_b.B[ch]; + aOptErr = fErr1; + do_b = 0; // do A next + } + + // now alternate endpoints and keep trying until there is no improvement + for (;;) + { + float fErr = PerturbOne(pEP, aColors, np, ch, aOptEndPts, newEndPts, aOptErr, do_b); + if (fErr >= aOptErr) + break; + if (do_b == 0) + aOptEndPts.A[ch] = newEndPts.A[ch]; + else + aOptEndPts.B[ch] = newEndPts.B[ch]; + aOptErr = fErr; + do_b = 1 - do_b; // now move the other endpoint + } + } +} + + +_Use_decl_annotations_ +void D3DX_BC6H::OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[], const INTEndPntPair aOrgEndPts[], INTEndPntPair aOptEndPts[]) const +{ + assert(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC6H_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS); + INTColor aPixels[NUM_PIXELS_PER_BLOCK]; + + for (size_t p = 0; p <= uPartitions; ++p) + { + // collect the pixels in the region + size_t np = 0; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + if (g_aPartitionTable[p][pEP->uShape][i] == p) + { + aPixels[np++] = pEP->aIPixels[i]; + } + } + + OptimizeOne(pEP, aPixels, np, aOrgErr[p], aOrgEndPts[p], aOptEndPts[p]); + } +} + + +// Swap endpoints as needed to ensure that the indices at fix up have a 0 high-order bit +_Use_decl_annotations_ +void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], size_t aIndices[]) +{ + assert(pEP); + const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + const size_t uNumIndices = size_t(1) << ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uHighIndexBit = uNumIndices >> 1; + + assert(uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + + for (size_t p = 0; p <= uPartitions; ++p) + { + size_t i = g_aFixUp[uPartitions][pEP->uShape][p]; + assert(g_aPartitionTable[uPartitions][pEP->uShape][i] == p); + if (aIndices[i] & uHighIndexBit) + { + // high bit is set, swap the aEndPts and indices for this region + std::swap(aEndPts[p].A, aEndPts[p].B); + + for (size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j) + if (g_aPartitionTable[uPartitions][pEP->uShape][j] == p) + aIndices[j] = uNumIndices - 1 - aIndices[j]; + } + } +} + + +// assign indices given a tile, shape, and quantized endpoints, return toterr for each region +_Use_decl_annotations_ +void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndPts[], size_t aIndices[], float aTotErr[]) const +{ + assert(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + const uint8_t uNumIndices = 1 << ms_aInfo[pEP->uMode].uIndexPrec; + + assert(uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + + // build list of possibles + INTColor aPalette[BC6H_MAX_REGIONS][BC6H_MAX_INDICES]; + + for (size_t p = 0; p <= uPartitions; ++p) + { + GeneratePaletteQuantized(pEP, aEndPts[p], aPalette[p]); + aTotErr[p] = 0; + } + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + const uint8_t uRegion = g_aPartitionTable[uPartitions][pEP->uShape][i]; + assert(uRegion < BC6H_MAX_REGIONS); + _Analysis_assume_(uRegion < BC6H_MAX_REGIONS); + float fBestErr = Norm(pEP->aIPixels[i], aPalette[uRegion][0]); + aIndices[i] = 0; + + for (uint8_t j = 1; j < uNumIndices && fBestErr > 0; ++j) + { + float fErr = Norm(pEP->aIPixels[i], aPalette[uRegion][j]); + if (fErr > fBestErr) break; // error increased, so we're done searching + if (fErr < fBestErr) + { + fBestErr = fErr; + aIndices[i] = j; + } + } + aTotErr[uRegion] += fBestErr; + } +} + + +_Use_decl_annotations_ +void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPts) const +{ + assert(pEP && aQntEndPts); + const INTEndPntPair* aUnqEndPts = pEP->aUnqEndPts[pEP->uShape]; + const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC6H_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS); + + for (size_t p = 0; p <= uPartitions; ++p) + { + aQntEndPts[p].A.r = Quantize(aUnqEndPts[p].A.r, Prec.r, pEP->bSigned); + aQntEndPts[p].A.g = Quantize(aUnqEndPts[p].A.g, Prec.g, pEP->bSigned); + aQntEndPts[p].A.b = Quantize(aUnqEndPts[p].A.b, Prec.b, pEP->bSigned); + aQntEndPts[p].B.r = Quantize(aUnqEndPts[p].B.r, Prec.r, pEP->bSigned); + aQntEndPts[p].B.g = Quantize(aUnqEndPts[p].B.g, Prec.g, pEP->bSigned); + aQntEndPts[p].B.b = Quantize(aUnqEndPts[p].B.b, Prec.b, pEP->bSigned); + } +} + + +_Use_decl_annotations_ +void D3DX_BC6H::EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[], const size_t aIndices[]) +{ + assert(pEP); + const uint8_t uRealMode = ms_aInfo[pEP->uMode].uMode; + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uHeaderBits = uPartitions > 0 ? 82 : 65; + const ModeDescriptor* desc = ms_aDesc[pEP->uMode]; + size_t uStartBit = 0; + + while (uStartBit < uHeaderBits) + { + switch (desc[uStartBit].m_eField) + { + case M: SetBit(uStartBit, uint8_t(uRealMode >> desc[uStartBit].m_uBit) & 0x01); break; + case D: SetBit(uStartBit, uint8_t(pEP->uShape >> desc[uStartBit].m_uBit) & 0x01); break; + case RW: SetBit(uStartBit, uint8_t(aEndPts[0].A.r >> desc[uStartBit].m_uBit) & 0x01); break; + case RX: SetBit(uStartBit, uint8_t(aEndPts[0].B.r >> desc[uStartBit].m_uBit) & 0x01); break; + case RY: SetBit(uStartBit, uint8_t(aEndPts[1].A.r >> desc[uStartBit].m_uBit) & 0x01); break; + case RZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.r >> desc[uStartBit].m_uBit) & 0x01); break; + case GW: SetBit(uStartBit, uint8_t(aEndPts[0].A.g >> desc[uStartBit].m_uBit) & 0x01); break; + case GX: SetBit(uStartBit, uint8_t(aEndPts[0].B.g >> desc[uStartBit].m_uBit) & 0x01); break; + case GY: SetBit(uStartBit, uint8_t(aEndPts[1].A.g >> desc[uStartBit].m_uBit) & 0x01); break; + case GZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.g >> desc[uStartBit].m_uBit) & 0x01); break; + case BW: SetBit(uStartBit, uint8_t(aEndPts[0].A.b >> desc[uStartBit].m_uBit) & 0x01); break; + case BX: SetBit(uStartBit, uint8_t(aEndPts[0].B.b >> desc[uStartBit].m_uBit) & 0x01); break; + case BY: SetBit(uStartBit, uint8_t(aEndPts[1].A.b >> desc[uStartBit].m_uBit) & 0x01); break; + case BZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.b >> desc[uStartBit].m_uBit) & 0x01); break; + default: assert(false); + } + } + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + if (IsFixUpOffset(ms_aInfo[pEP->uMode].uPartitions, pEP->uShape, i)) + SetBits(uStartBit, uIndexPrec - 1, static_cast(aIndices[i])); + else + SetBits(uStartBit, uIndexPrec, static_cast(aIndices[i])); + } + assert(uStartBit == 128); +} + + +_Use_decl_annotations_ +void D3DX_BC6H::Refine(EncodeParams* pEP) +{ + assert(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC6H_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS); + + const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed; + float aOrgErr[BC6H_MAX_REGIONS], aOptErr[BC6H_MAX_REGIONS]; + INTEndPntPair aOrgEndPts[BC6H_MAX_REGIONS], aOptEndPts[BC6H_MAX_REGIONS]; + size_t aOrgIdx[NUM_PIXELS_PER_BLOCK], aOptIdx[NUM_PIXELS_PER_BLOCK]; + + QuantizeEndPts(pEP, aOrgEndPts); + AssignIndices(pEP, aOrgEndPts, aOrgIdx, aOrgErr); + SwapIndices(pEP, aOrgEndPts, aOrgIdx); + + if (bTransformed) TransformForward(aOrgEndPts); + if (EndPointsFit(pEP, aOrgEndPts)) + { + if (bTransformed) TransformInverse(aOrgEndPts, ms_aInfo[pEP->uMode].RGBAPrec[0][0], pEP->bSigned); + OptimizeEndPoints(pEP, aOrgErr, aOrgEndPts, aOptEndPts); + AssignIndices(pEP, aOptEndPts, aOptIdx, aOptErr); + SwapIndices(pEP, aOptEndPts, aOptIdx); + + float fOrgTotErr = 0.0f, fOptTotErr = 0.0f; + for (size_t p = 0; p <= uPartitions; ++p) + { + fOrgTotErr += aOrgErr[p]; + fOptTotErr += aOptErr[p]; + } + + if (bTransformed) TransformForward(aOptEndPts); + if (EndPointsFit(pEP, aOptEndPts) && fOptTotErr < fOrgTotErr && fOptTotErr < pEP->fBestErr) + { + pEP->fBestErr = fOptTotErr; + EmitBlock(pEP, aOptEndPts, aOptIdx); + } + else if (fOrgTotErr < pEP->fBestErr) + { + // either it stopped fitting when we optimized it, or there was no improvement + // so go back to the unoptimized endpoints which we know will fit + if (bTransformed) TransformForward(aOrgEndPts); + pEP->fBestErr = fOrgTotErr; + EmitBlock(pEP, aOrgEndPts, aOrgIdx); + } + } +} + + +_Use_decl_annotations_ +void D3DX_BC6H::GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegion, INTColor aPalette[]) +{ + assert(pEP); + assert(uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + _Analysis_assume_(uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + const INTEndPntPair& endPts = pEP->aUnqEndPts[pEP->uShape][uRegion]; + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const uint8_t uNumIndices = 1 << uIndexPrec; + assert(uNumIndices > 0); + _Analysis_assume_(uNumIndices > 0); + + const int* aWeights = nullptr; + switch (uIndexPrec) + { + case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); _Analysis_assume_(uNumIndices <= 8); break; + case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); _Analysis_assume_(uNumIndices <= 16); break; + default: + assert(false); + for (size_t i = 0; i < uNumIndices; ++i) + { +#pragma prefast(suppress:22102 22103, "writing blocks in two halves confuses tool") + aPalette[i] = INTColor(0, 0, 0); + } + return; + } + + for (size_t i = 0; i < uNumIndices; ++i) + { + aPalette[i].r = (endPts.A.r * (BC67_WEIGHT_MAX - aWeights[i]) + endPts.B.r * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT; + aPalette[i].g = (endPts.A.g * (BC67_WEIGHT_MAX - aWeights[i]) + endPts.B.g * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT; + aPalette[i].b = (endPts.A.b * (BC67_WEIGHT_MAX - aWeights[i]) + endPts.B.b * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT; + } +} + + +_Use_decl_annotations_ +float D3DX_BC6H::MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, const size_t* auIndex) const +{ + assert(pEP); + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const uint8_t uNumIndices = 1 << uIndexPrec; + INTColor aPalette[BC6H_MAX_INDICES]; + GeneratePaletteUnquantized(pEP, uRegion, aPalette); + + float fTotalErr = 0.0f; + for (size_t i = 0; i < np; ++i) + { + float fBestErr = Norm(pEP->aIPixels[auIndex[i]], aPalette[0]); + for (uint8_t j = 1; j < uNumIndices && fBestErr > 0.0f; ++j) + { + float fErr = Norm(pEP->aIPixels[auIndex[i]], aPalette[j]); + if (fErr > fBestErr) break; // error increased, so we're done searching + if (fErr < fBestErr) fBestErr = fErr; + } + fTotalErr += fBestErr; + } + + return fTotalErr; +} + +_Use_decl_annotations_ +float D3DX_BC6H::RoughMSE(EncodeParams* pEP) const +{ + assert(pEP); + assert(pEP->uShape < BC6H_MAX_SHAPES); + _Analysis_assume_(pEP->uShape < BC6H_MAX_SHAPES); + + INTEndPntPair* aEndPts = pEP->aUnqEndPts[pEP->uShape]; + + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC6H_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC6H_MAX_REGIONS); + + size_t auPixIdx[NUM_PIXELS_PER_BLOCK]; + + float fError = 0.0f; + for (size_t p = 0; p <= uPartitions; ++p) + { + size_t np = 0; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + if (g_aPartitionTable[uPartitions][pEP->uShape][i] == p) + { + auPixIdx[np++] = i; + } + } + + // handle simple cases + assert(np > 0); + if (np == 1) + { + aEndPts[p].A = pEP->aIPixels[auPixIdx[0]]; + aEndPts[p].B = pEP->aIPixels[auPixIdx[0]]; + continue; + } + else if (np == 2) + { + aEndPts[p].A = pEP->aIPixels[auPixIdx[0]]; + aEndPts[p].B = pEP->aIPixels[auPixIdx[1]]; + continue; + } + + HDRColorA epA, epB; + OptimizeRGB(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx); + aEndPts[p].A.Set(epA, pEP->bSigned); + aEndPts[p].B.Set(epB, pEP->bSigned); + if (pEP->bSigned) + { + aEndPts[p].A.Clamp(-F16MAX, F16MAX); + aEndPts[p].B.Clamp(-F16MAX, F16MAX); + } + else + { + aEndPts[p].A.Clamp(0, F16MAX); + aEndPts[p].B.Clamp(0, F16MAX); + } + + fError += MapColors(pEP, p, np, auPixIdx); + } + + return fError; +} + + +//------------------------------------------------------------------------------------- +// BC7 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void D3DX_BC7::Decode(HDRColorA* pOut) const +{ + assert(pOut); + + size_t uFirst = 0; + while (uFirst < 128 && !GetBit(uFirst)) {} + uint8_t uMode = uint8_t(uFirst - 1); + + if (uMode < 8) + { + const uint8_t uPartitions = ms_aInfo[uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC7_MAX_REGIONS); + + const uint8_t uNumEndPts = (uPartitions + 1) << 1; + const uint8_t uIndexPrec = ms_aInfo[uMode].uIndexPrec; + const uint8_t uIndexPrec2 = ms_aInfo[uMode].uIndexPrec2; + size_t i; + size_t uStartBit = uMode + 1; + uint8_t P[6]; + uint8_t uShape = GetBits(uStartBit, ms_aInfo[uMode].uPartitionBits); + assert(uShape < BC7_MAX_SHAPES); + _Analysis_assume_(uShape < BC7_MAX_SHAPES); + + uint8_t uRotation = GetBits(uStartBit, ms_aInfo[uMode].uRotationBits); + assert(uRotation < 4); + + uint8_t uIndexMode = GetBits(uStartBit, ms_aInfo[uMode].uIndexModeBits); + assert(uIndexMode < 2); + + LDRColorA c[BC7_MAX_REGIONS << 1]; + const LDRColorA RGBAPrec = ms_aInfo[uMode].RGBAPrec; + const LDRColorA RGBAPrecWithP = ms_aInfo[uMode].RGBAPrecWithP; + + assert(uNumEndPts <= (BC7_MAX_REGIONS << 1)); + + // Red channel + for (i = 0; i < uNumEndPts; i++) + { + if (uStartBit + RGBAPrec.r > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].r = GetBits(uStartBit, RGBAPrec.r); + } + + // Green channel + for (i = 0; i < uNumEndPts; i++) + { + if (uStartBit + RGBAPrec.g > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].g = GetBits(uStartBit, RGBAPrec.g); + } + + // Blue channel + for (i = 0; i < uNumEndPts; i++) + { + if (uStartBit + RGBAPrec.b > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].b = GetBits(uStartBit, RGBAPrec.b); + } + + // Alpha channel + for (i = 0; i < uNumEndPts; i++) + { + if (uStartBit + RGBAPrec.a > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + c[i].a = RGBAPrec.a ? GetBits(uStartBit, RGBAPrec.a) : 255; + } + + // P-bits + assert(ms_aInfo[uMode].uPBits <= 6); + _Analysis_assume_(ms_aInfo[uMode].uPBits <= 6); + for (i = 0; i < ms_aInfo[uMode].uPBits; i++) + { + if (uStartBit > 127) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + P[i] = GetBit(uStartBit); + } + + if (ms_aInfo[uMode].uPBits) + { + for (i = 0; i < uNumEndPts; i++) + { + size_t pi = i * ms_aInfo[uMode].uPBits / uNumEndPts; + for (uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++) + { + if (RGBAPrec[ch] != RGBAPrecWithP[ch]) + { + c[i][ch] = (c[i][ch] << 1) | P[pi]; + } + } + } + } + + for (i = 0; i < uNumEndPts; i++) + { + c[i] = Unquantize(c[i], RGBAPrecWithP); + } + + uint8_t w1[NUM_PIXELS_PER_BLOCK], w2[NUM_PIXELS_PER_BLOCK]; + + // read color indices + for (i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + { + size_t uNumBits = IsFixUpOffset(ms_aInfo[uMode].uPartitions, uShape, i) ? uIndexPrec - 1 : uIndexPrec; + if (uStartBit + uNumBits > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + w1[i] = GetBits(uStartBit, uNumBits); + } + + // read alpha indices + if (uIndexPrec2) + { + for (i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + { + size_t uNumBits = i ? uIndexPrec2 : uIndexPrec2 - 1; + if (uStartBit + uNumBits > 128) + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + w2[i] = GetBits(uStartBit, uNumBits); + } + } + + for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i]; + LDRColorA outPixel; + if (uIndexPrec2 == 0) + { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w1[i], uIndexPrec, uIndexPrec, outPixel); + } + else + { + if (uIndexMode == 0) + { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w2[i], uIndexPrec, uIndexPrec2, outPixel); + } + else + { + LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w2[i], w1[i], uIndexPrec2, uIndexPrec, outPixel); + } + } + + switch (uRotation) + { + case 1: std::swap(outPixel.r, outPixel.a); break; + case 2: std::swap(outPixel.g, outPixel.a); break; + case 3: std::swap(outPixel.b, outPixel.a); break; + } + + pOut[i] = HDRColorA(outPixel); + } + } + else + { +#ifdef _DEBUG + OutputDebugStringA("BC7: Reserved mode 8 encountered during decoding\n"); +#endif + // Per the BC7 format spec, we must return transparent black + memset(pOut, 0, sizeof(HDRColorA) * NUM_PIXELS_PER_BLOCK); + } +} + +_Use_decl_annotations_ +void D3DX_BC7::Encode(DWORD flags, const HDRColorA* const pIn) +{ + assert(pIn); + + D3DX_BC7 final = *this; + EncodeParams EP(pIn); + float fMSEBest = FLT_MAX; + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + EP.aLDRPixels[i].r = uint8_t(std::max(0.0f, std::min(255.0f, pIn[i].r * 255.0f + 0.01f))); + EP.aLDRPixels[i].g = uint8_t(std::max(0.0f, std::min(255.0f, pIn[i].g * 255.0f + 0.01f))); + EP.aLDRPixels[i].b = uint8_t(std::max(0.0f, std::min(255.0f, pIn[i].b * 255.0f + 0.01f))); + EP.aLDRPixels[i].a = uint8_t(std::max(0.0f, std::min(255.0f, pIn[i].a * 255.0f + 0.01f))); + } + + for (EP.uMode = 0; EP.uMode < 8 && fMSEBest > 0; ++EP.uMode) + { + if (!(flags & BC_FLAGS_USE_3SUBSETS) && (EP.uMode == 0 || EP.uMode == 2)) + { + // 3 subset modes tend to be used rarely and add significant compression time + continue; + } + + if ((flags & TEX_COMPRESS_BC7_QUICK) && (EP.uMode != 6)) + { + // Use only mode 6 + continue; + } + + const size_t uShapes = size_t(1) << ms_aInfo[EP.uMode].uPartitionBits; + assert(uShapes <= BC7_MAX_SHAPES); + _Analysis_assume_(uShapes <= BC7_MAX_SHAPES); + + const size_t uNumRots = size_t(1) << ms_aInfo[EP.uMode].uRotationBits; + const size_t uNumIdxMode = size_t(1) << ms_aInfo[EP.uMode].uIndexModeBits; + // Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes + // uShapes/4 gets nearly all the cases; you can increase that a bit (say by 3 or 4) if you really want to squeeze the last bit out + const size_t uItems = std::max(1, uShapes >> 2); + float afRoughMSE[BC7_MAX_SHAPES]; + size_t auShape[BC7_MAX_SHAPES]; + + for (size_t r = 0; r < uNumRots && fMSEBest > 0; ++r) + { + switch (r) + { + case 1: for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break; + case 2: for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break; + case 3: for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break; + } + + for (size_t im = 0; im < uNumIdxMode && fMSEBest > 0; ++im) + { + // pick the best uItems shapes and refine these. + for (size_t s = 0; s < uShapes; s++) + { + afRoughMSE[s] = RoughMSE(&EP, s, im); + auShape[s] = s; + } + + // Bubble up the first uItems items + for (size_t i = 0; i < uItems; i++) + { + for (size_t j = i + 1; j < uShapes; j++) + { + if (afRoughMSE[i] > afRoughMSE[j]) + { + std::swap(afRoughMSE[i], afRoughMSE[j]); + std::swap(auShape[i], auShape[j]); + } + } + } + + for (size_t i = 0; i < uItems && fMSEBest > 0; i++) + { + float fMSE = Refine(&EP, auShape[i], r, im); + if (fMSE < fMSEBest) + { + final = *this; + fMSEBest = fMSE; + } + } + } + + switch (r) + { + case 1: for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break; + case 2: for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break; + case 3: for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break; + } + } + } + + *this = final; +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void D3DX_BC7::GeneratePaletteQuantized(const EncodeParams* pEP, size_t uIndexMode, const LDREndPntPair& endPts, LDRColorA aPalette[]) const +{ + assert(pEP); + const size_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2; + const size_t uNumIndices = size_t(1) << uIndexPrec; + const size_t uNumIndices2 = size_t(1) << uIndexPrec2; + assert(uNumIndices > 0 && uNumIndices2 > 0); + _Analysis_assume_(uNumIndices > 0 && uNumIndices2 > 0); + assert((uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES)); + _Analysis_assume_((uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES)); + + LDRColorA a = Unquantize(endPts.A, ms_aInfo[pEP->uMode].RGBAPrecWithP); + LDRColorA b = Unquantize(endPts.B, ms_aInfo[pEP->uMode].RGBAPrecWithP); + if (uIndexPrec2 == 0) + { + for (size_t i = 0; i < uNumIndices; i++) + LDRColorA::Interpolate(a, b, i, i, uIndexPrec, uIndexPrec, aPalette[i]); + } + else + { + for (size_t i = 0; i < uNumIndices; i++) + LDRColorA::InterpolateRGB(a, b, i, uIndexPrec, aPalette[i]); + for (size_t i = 0; i < uNumIndices2; i++) + LDRColorA::InterpolateA(a, b, i, uIndexPrec2, aPalette[i]); + } +} + +_Use_decl_annotations_ +float D3DX_BC7::PerturbOne(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, size_t ch, + const LDREndPntPair &oldEndPts, LDREndPntPair &newEndPts, float fOldErr, uint8_t do_b) const +{ + assert(pEP); + const int prec = ms_aInfo[pEP->uMode].RGBAPrecWithP[ch]; + LDREndPntPair tmp_endPts = newEndPts = oldEndPts; + float fMinErr = fOldErr; + uint8_t* pnew_c = (do_b ? &newEndPts.B[ch] : &newEndPts.A[ch]); + uint8_t* ptmp_c = (do_b ? &tmp_endPts.B[ch] : &tmp_endPts.A[ch]); + + // do a logarithmic search for the best error for this endpoint (which) + for (int step = 1 << (prec - 1); step; step >>= 1) + { + bool bImproved = false; + int beststep = 0; + for (int sign = -1; sign <= 1; sign += 2) + { + int tmp = int(*pnew_c) + sign * step; + if (tmp < 0 || tmp >= (1 << prec)) + continue; + else + *ptmp_c = (uint8_t)tmp; + + float fTotalErr = MapColors(pEP, aColors, np, uIndexMode, tmp_endPts, fMinErr); + if (fTotalErr < fMinErr) + { + bImproved = true; + fMinErr = fTotalErr; + beststep = sign * step; + } + } + + // if this was an improvement, move the endpoint and continue search from there + if (bImproved) + *pnew_c = uint8_t(int(*pnew_c) + beststep); + } + return fMinErr; +} + +// perturb the endpoints at least -3 to 3. +// always ensure endpoint ordering is preserved (no need to overlap the scan) +_Use_decl_annotations_ +void D3DX_BC7::Exhaustive(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, size_t ch, + float& fOrgErr, LDREndPntPair& optEndPt) const +{ + assert(pEP); + const uint8_t uPrec = ms_aInfo[pEP->uMode].RGBAPrecWithP[ch]; + LDREndPntPair tmpEndPt; + if (fOrgErr == 0) + return; + + int delta = 5; + + // ok figure out the range of A and B + tmpEndPt = optEndPt; + int alow = std::max(0, int(optEndPt.A[ch]) - delta); + int ahigh = std::min((1 << uPrec) - 1, int(optEndPt.A[ch]) + delta); + int blow = std::max(0, int(optEndPt.B[ch]) - delta); + int bhigh = std::min((1 << uPrec) - 1, int(optEndPt.B[ch]) + delta); + int amin = 0; + int bmin = 0; + + float fBestErr = fOrgErr; + if (optEndPt.A[ch] <= optEndPt.B[ch]) + { + // keep a <= b + for (int a = alow; a <= ahigh; ++a) + { + for (int b = std::max(a, blow); b < bhigh; ++b) + { + tmpEndPt.A[ch] = (uint8_t)a; + tmpEndPt.B[ch] = (uint8_t)b; + + float fErr = MapColors(pEP, aColors, np, uIndexMode, tmpEndPt, fBestErr); + if (fErr < fBestErr) + { + amin = a; + bmin = b; + fBestErr = fErr; + } + } + } + } + else + { + // keep b <= a + for (int b = blow; b < bhigh; ++b) + { + for (int a = std::max(b, alow); a <= ahigh; ++a) + { + tmpEndPt.A[ch] = (uint8_t)a; + tmpEndPt.B[ch] = (uint8_t)b; + + float fErr = MapColors(pEP, aColors, np, uIndexMode, tmpEndPt, fBestErr); + if (fErr < fBestErr) + { + amin = a; + bmin = b; + fBestErr = fErr; + } + } + } + } + + if (fBestErr < fOrgErr) + { + optEndPt.A[ch] = (uint8_t)amin; + optEndPt.B[ch] = (uint8_t)bmin; + fOrgErr = fBestErr; + } +} + +_Use_decl_annotations_ +void D3DX_BC7::OptimizeOne(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, + float fOrgErr, const LDREndPntPair& org, LDREndPntPair& opt) const +{ + assert(pEP); + + float fOptErr = fOrgErr; + opt = org; + + LDREndPntPair new_a, new_b; + LDREndPntPair newEndPts; + uint8_t do_b; + + // now optimize each channel separately + for (size_t ch = 0; ch < BC7_NUM_CHANNELS; ++ch) + { + if (ms_aInfo[pEP->uMode].RGBAPrecWithP[ch] == 0) + continue; + + // figure out which endpoint when perturbed gives the most improvement and start there + // if we just alternate, we can easily end up in a local minima + float fErr0 = PerturbOne(pEP, aColors, np, uIndexMode, ch, opt, new_a, fOptErr, 0); // perturb endpt A + float fErr1 = PerturbOne(pEP, aColors, np, uIndexMode, ch, opt, new_b, fOptErr, 1); // perturb endpt B + + uint8_t& copt_a = opt.A[ch]; + uint8_t& copt_b = opt.B[ch]; + uint8_t& cnew_a = new_a.A[ch]; + uint8_t& cnew_b = new_a.B[ch]; + + if (fErr0 < fErr1) + { + if (fErr0 >= fOptErr) + continue; + copt_a = cnew_a; + fOptErr = fErr0; + do_b = 1; // do B next + } + else + { + if (fErr1 >= fOptErr) + continue; + copt_b = cnew_b; + fOptErr = fErr1; + do_b = 0; // do A next + } + + // now alternate endpoints and keep trying until there is no improvement + for (; ; ) + { + float fErr = PerturbOne(pEP, aColors, np, uIndexMode, ch, opt, newEndPts, fOptErr, do_b); + if (fErr >= fOptErr) + break; + if (do_b == 0) + copt_a = cnew_a; + else + copt_b = cnew_b; + fOptErr = fErr; + do_b = 1 - do_b; // now move the other endpoint + } + } + + // finally, do a small exhaustive search around what we think is the global minima to be sure + for (size_t ch = 0; ch < BC7_NUM_CHANNELS; ch++) + Exhaustive(pEP, aColors, np, uIndexMode, ch, fOptErr, opt); +} + +_Use_decl_annotations_ +void D3DX_BC7::OptimizeEndPoints(const EncodeParams* pEP, size_t uShape, size_t uIndexMode, const float afOrgErr[], + const LDREndPntPair aOrgEndPts[], LDREndPntPair aOptEndPts[]) const +{ + assert(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES); + _Analysis_assume_(uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES); + + LDRColorA aPixels[NUM_PIXELS_PER_BLOCK]; + + for (size_t p = 0; p <= uPartitions; ++p) + { + // collect the pixels in the region + size_t np = 0; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + if (g_aPartitionTable[uPartitions][uShape][i] == p) + aPixels[np++] = pEP->aLDRPixels[i]; + + OptimizeOne(pEP, aPixels, np, uIndexMode, afOrgErr[p], aOrgEndPts[p], aOptEndPts[p]); + } +} + +_Use_decl_annotations_ +void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uIndexMode, LDREndPntPair endPts[], size_t aIndices[], size_t aIndices2[], + float afTotErr[]) const +{ + assert(pEP); + assert(uShape < BC7_MAX_SHAPES); + _Analysis_assume_(uShape < BC7_MAX_SHAPES); + + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC7_MAX_REGIONS); + + const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec; + const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2; + const uint8_t uNumIndices = 1 << uIndexPrec; + const uint8_t uNumIndices2 = 1 << uIndexPrec2; + + assert((uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES)); + _Analysis_assume_((uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES)); + + const uint8_t uHighestIndexBit = uNumIndices >> 1; + const uint8_t uHighestIndexBit2 = uNumIndices2 >> 1; + LDRColorA aPalette[BC7_MAX_REGIONS][BC7_MAX_INDICES]; + + // build list of possibles + for (size_t p = 0; p <= uPartitions; p++) + { + GeneratePaletteQuantized(pEP, uIndexMode, endPts[p], aPalette[p]); + afTotErr[p] = 0; + } + + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + { + uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i]; + assert(uRegion < BC7_MAX_REGIONS); + _Analysis_assume_(uRegion < BC7_MAX_REGIONS); + afTotErr[uRegion] += ComputeError(pEP->aLDRPixels[i], aPalette[uRegion], uIndexPrec, uIndexPrec2, &(aIndices[i]), &(aIndices2[i])); + } + + // swap endpoints as needed to ensure that the indices at index_positions have a 0 high-order bit + if (uIndexPrec2 == 0) + { + for (size_t p = 0; p <= uPartitions; p++) + { + if (aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit) + { + std::swap(endPts[p].A, endPts[p].B); + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + if (g_aPartitionTable[uPartitions][uShape][i] == p) + aIndices[i] = uNumIndices - 1 - aIndices[i]; + } + assert((aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit) == 0); + } + } + else + { + for (size_t p = 0; p <= uPartitions; p++) + { + if (aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit) + { + std::swap(endPts[p].A.r, endPts[p].B.r); + std::swap(endPts[p].A.g, endPts[p].B.g); + std::swap(endPts[p].A.b, endPts[p].B.b); + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + if (g_aPartitionTable[uPartitions][uShape][i] == p) + aIndices[i] = uNumIndices - 1 - aIndices[i]; + } + assert((aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit) == 0); + + if (aIndices2[0] & uHighestIndexBit2) + { + std::swap(endPts[p].A.a, endPts[p].B.a); + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + aIndices2[i] = uNumIndices2 - 1 - aIndices2[i]; + } + assert((aIndices2[0] & uHighestIndexBit2) == 0); + } + } +} + +_Use_decl_annotations_ +void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode, const LDREndPntPair aEndPts[], const size_t aIndex[], const size_t aIndex2[]) +{ + assert(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC7_MAX_REGIONS); + + const size_t uPBits = ms_aInfo[pEP->uMode].uPBits; + const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uIndexPrec2 = ms_aInfo[pEP->uMode].uIndexPrec2; + const LDRColorA RGBAPrec = ms_aInfo[pEP->uMode].RGBAPrec; + const LDRColorA RGBAPrecWithP = ms_aInfo[pEP->uMode].RGBAPrecWithP; + size_t i; + size_t uStartBit = 0; + SetBits(uStartBit, pEP->uMode, 0); + SetBits(uStartBit, 1, 1); + SetBits(uStartBit, ms_aInfo[pEP->uMode].uRotationBits, static_cast(uRotation)); + SetBits(uStartBit, ms_aInfo[pEP->uMode].uIndexModeBits, static_cast(uIndexMode)); + SetBits(uStartBit, ms_aInfo[pEP->uMode].uPartitionBits, static_cast(uShape)); + + if (uPBits) + { + const size_t uNumEP = size_t(1 + uPartitions) << 1; + uint8_t aPVote[BC7_MAX_REGIONS << 1] = { 0,0,0,0,0,0 }; + uint8_t aCount[BC7_MAX_REGIONS << 1] = { 0,0,0,0,0,0 }; + for (uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++) + { + uint8_t ep = 0; + for (i = 0; i <= uPartitions; i++) + { + if (RGBAPrec[ch] == RGBAPrecWithP[ch]) + { + SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].A[ch]); + SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch]); + } + else + { + SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].A[ch] >> 1); + SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch] >> 1); + size_t idx = ep++ * uPBits / uNumEP; + assert(idx < (BC7_MAX_REGIONS << 1)); + _Analysis_assume_(idx < (BC7_MAX_REGIONS << 1)); + aPVote[idx] += aEndPts[i].A[ch] & 0x01; + aCount[idx]++; + idx = ep++ * uPBits / uNumEP; + assert(idx < (BC7_MAX_REGIONS << 1)); + _Analysis_assume_(idx < (BC7_MAX_REGIONS << 1)); + aPVote[idx] += aEndPts[i].B[ch] & 0x01; + aCount[idx]++; + } + } + } + + for (i = 0; i < uPBits; i++) + { + SetBits(uStartBit, 1, aPVote[i] > (aCount[i] >> 1) ? 1 : 0); + } + } + else + { + for (size_t ch = 0; ch < BC7_NUM_CHANNELS; ch++) + { + for (i = 0; i <= uPartitions; i++) + { + SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].A[ch]); + SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch]); + } + } + } + + const size_t* aI1 = uIndexMode ? aIndex2 : aIndex; + const size_t* aI2 = uIndexMode ? aIndex : aIndex2; + for (i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + { + if (IsFixUpOffset(ms_aInfo[pEP->uMode].uPartitions, uShape, i)) + SetBits(uStartBit, uIndexPrec - 1, static_cast(aI1[i])); + else + SetBits(uStartBit, uIndexPrec, static_cast(aI1[i])); + } + if (uIndexPrec2) + for (i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + SetBits(uStartBit, i ? uIndexPrec2 : uIndexPrec2 - 1, static_cast(aI2[i])); + + assert(uStartBit == 128); +} + +_Use_decl_annotations_ +float D3DX_BC7::Refine(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode) +{ + assert( pEP ); + assert( uShape < BC7_MAX_SHAPES ); + _Analysis_assume_( uShape < BC7_MAX_SHAPES ); + const LDREndPntPair* aEndPts = pEP->aEndPts[uShape]; + + const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert( uPartitions < BC7_MAX_REGIONS ); + _Analysis_assume_( uPartitions < BC7_MAX_REGIONS ); + + LDREndPntPair aOrgEndPts[BC7_MAX_REGIONS]; + LDREndPntPair aOptEndPts[BC7_MAX_REGIONS]; + size_t aOrgIdx[NUM_PIXELS_PER_BLOCK]; + size_t aOrgIdx2[NUM_PIXELS_PER_BLOCK]; + size_t aOptIdx[NUM_PIXELS_PER_BLOCK]; + size_t aOptIdx2[NUM_PIXELS_PER_BLOCK]; + float aOrgErr[BC7_MAX_REGIONS]; + float aOptErr[BC7_MAX_REGIONS]; + + for(size_t p = 0; p <= uPartitions; p++) + { + aOrgEndPts[p].A = Quantize(aEndPts[p].A, ms_aInfo[pEP->uMode].RGBAPrecWithP); + aOrgEndPts[p].B = Quantize(aEndPts[p].B, ms_aInfo[pEP->uMode].RGBAPrecWithP); + } + + AssignIndices(pEP, uShape, uIndexMode, aOrgEndPts, aOrgIdx, aOrgIdx2, aOrgErr); + OptimizeEndPoints(pEP, uShape, uIndexMode, aOrgErr, aOrgEndPts, aOptEndPts); + AssignIndices(pEP, uShape, uIndexMode, aOptEndPts, aOptIdx, aOptIdx2, aOptErr); + + float fOrgTotErr = 0, fOptTotErr = 0; + for(size_t p = 0; p <= uPartitions; p++) + { + fOrgTotErr += aOrgErr[p]; + fOptTotErr += aOptErr[p]; + } + if(fOptTotErr < fOrgTotErr) + { + EmitBlock(pEP, uShape, uRotation, uIndexMode, aOptEndPts, aOptIdx, aOptIdx2); + return fOptTotErr; + } + else + { + EmitBlock(pEP, uShape, uRotation, uIndexMode, aOrgEndPts, aOrgIdx, aOrgIdx2); + return fOrgTotErr; + } +} + +_Use_decl_annotations_ +float D3DX_BC7::MapColors(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, const LDREndPntPair& endPts, float fMinErr) const +{ + assert(pEP); + const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec; + const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2; + LDRColorA aPalette[BC7_MAX_INDICES]; + float fTotalErr = 0; + + GeneratePaletteQuantized(pEP, uIndexMode, endPts, aPalette); + for (size_t i = 0; i < np; ++i) + { + fTotalErr += ComputeError(aColors[i], aPalette, uIndexPrec, uIndexPrec2); + if (fTotalErr > fMinErr) // check for early exit + { + fTotalErr = FLT_MAX; + break; + } + } + + return fTotalErr; +} + +_Use_decl_annotations_ +float D3DX_BC7::RoughMSE(EncodeParams* pEP, size_t uShape, size_t uIndexMode) +{ + assert(pEP); + assert(uShape < BC7_MAX_SHAPES); + _Analysis_assume_(uShape < BC7_MAX_SHAPES); + LDREndPntPair* aEndPts = pEP->aEndPts[uShape]; + + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + assert(uPartitions < BC7_MAX_REGIONS); + _Analysis_assume_(uPartitions < BC7_MAX_REGIONS); + + const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec; + const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2; + const uint8_t uNumIndices = 1 << uIndexPrec; + const uint8_t uNumIndices2 = 1 << uIndexPrec2; + size_t auPixIdx[NUM_PIXELS_PER_BLOCK]; + LDRColorA aPalette[BC7_MAX_REGIONS][BC7_MAX_INDICES]; + + for (size_t p = 0; p <= uPartitions; p++) + { + size_t np = 0; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + { + if (g_aPartitionTable[uPartitions][uShape][i] == p) + { + auPixIdx[np++] = i; + } + } + + // handle simple cases + assert(np > 0); + if (np == 1) + { + aEndPts[p].A = pEP->aLDRPixels[auPixIdx[0]]; + aEndPts[p].B = pEP->aLDRPixels[auPixIdx[0]]; + continue; + } + else if (np == 2) + { + aEndPts[p].A = pEP->aLDRPixels[auPixIdx[0]]; + aEndPts[p].B = pEP->aLDRPixels[auPixIdx[1]]; + continue; + } + + if (uIndexPrec2 == 0) + { + HDRColorA epA, epB; + OptimizeRGBA(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx); + epA.Clamp(0.0f, 1.0f); + epB.Clamp(0.0f, 1.0f); + epA *= 255.0f; + epB *= 255.0f; + aEndPts[p].A = epA.ToLDRColorA(); + aEndPts[p].B = epB.ToLDRColorA(); + } + else + { + uint8_t uMinAlpha = 255, uMaxAlpha = 0; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i) + { + uMinAlpha = std::min(uMinAlpha, pEP->aLDRPixels[auPixIdx[i]].a); + uMaxAlpha = std::max(uMaxAlpha, pEP->aLDRPixels[auPixIdx[i]].a); + } + + HDRColorA epA, epB; + OptimizeRGB(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx); + epA.Clamp(0.0f, 1.0f); + epB.Clamp(0.0f, 1.0f); + epA *= 255.0f; + epB *= 255.0f; + aEndPts[p].A = epA.ToLDRColorA(); + aEndPts[p].B = epB.ToLDRColorA(); + aEndPts[p].A.a = uMinAlpha; + aEndPts[p].B.a = uMaxAlpha; + } + } + + if (uIndexPrec2 == 0) + { + for (size_t p = 0; p <= uPartitions; p++) + for (size_t i = 0; i < uNumIndices; i++) + LDRColorA::Interpolate(aEndPts[p].A, aEndPts[p].B, i, i, uIndexPrec, uIndexPrec, aPalette[p][i]); + } + else + { + for (size_t p = 0; p <= uPartitions; p++) + { + for (size_t i = 0; i < uNumIndices; i++) + LDRColorA::InterpolateRGB(aEndPts[p].A, aEndPts[p].B, i, uIndexPrec, aPalette[p][i]); + for (size_t i = 0; i < uNumIndices2; i++) + LDRColorA::InterpolateA(aEndPts[p].A, aEndPts[p].B, i, uIndexPrec2, aPalette[p][i]); + } + } + + float fTotalErr = 0; + for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) + { + uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i]; + fTotalErr += ComputeError(pEP->aLDRPixels[i], aPalette[uRegion], uIndexPrec, uIndexPrec2); + } + + return fTotalErr; +} + + +//===================================================================================== +// Entry points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// BC6H Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC6HU(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pBC)->Decode(false, reinterpret_cast(pColor)); +} + +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC6HS(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pBC)->Decode(true, reinterpret_cast(pColor)); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC6HU(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + UNREFERENCED_PARAMETER(flags); + assert(pBC && pColor); + static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pBC)->Encode(false, reinterpret_cast(pColor)); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC6HS(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + UNREFERENCED_PARAMETER(flags); + assert(pBC && pColor); + static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pBC)->Encode(true, reinterpret_cast(pColor)); +} + + +//------------------------------------------------------------------------------------- +// BC7 Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::D3DXDecodeBC7(XMVECTOR *pColor, const uint8_t *pBC) +{ + assert(pColor && pBC); + static_assert(sizeof(D3DX_BC7) == 16, "D3DX_BC7 should be 16 bytes"); + reinterpret_cast(pBC)->Decode(reinterpret_cast(pColor)); +} + +_Use_decl_annotations_ +void DirectX::D3DXEncodeBC7(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags) +{ + assert(pBC && pColor); + static_assert(sizeof(D3DX_BC7) == 16, "D3DX_BC7 should be 16 bytes"); + reinterpret_cast(pBC)->Encode(flags, reinterpret_cast(pColor)); +} diff --git a/Kits/DirectXTex/BCDirectCompute.cpp b/Kits/DirectXTex/BCDirectCompute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a063b7854554ff835da9ada8c0657270d97ce66 --- /dev/null +++ b/Kits/DirectXTex/BCDirectCompute.cpp @@ -0,0 +1,613 @@ +//------------------------------------------------------------------------------------- +// BCDirectCompute.cpp +// +// Direct3D 11 Compute Shader BC Compressor +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "BCDirectCompute.h" + +#if defined(_DEBUG) || defined(PROFILE) +#pragma comment(lib,"dxguid.lib") +#endif + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + #include "Shaders\Compiled\BC7Encode_EncodeBlockCS.inc" + #include "Shaders\Compiled\BC7Encode_TryMode02CS.inc" + #include "Shaders\Compiled\BC7Encode_TryMode137CS.inc" + #include "Shaders\Compiled\BC7Encode_TryMode456CS.inc" + #include "Shaders\Compiled\BC6HEncode_EncodeBlockCS.inc" + #include "Shaders\Compiled\BC6HEncode_TryModeG10CS.inc" + #include "Shaders\Compiled\BC6HEncode_TryModeLE10CS.inc" + + struct BufferBC6HBC7 + { + UINT color[4]; + }; + + struct ConstantsBC6HBC7 + { + UINT tex_width; + UINT num_block_x; + UINT format; + UINT mode_id; + UINT start_block_id; + UINT num_total_blocks; + float alpha_weight; + UINT reserved; + }; + + static_assert( sizeof(ConstantsBC6HBC7) == sizeof(UINT)*8, "Constant buffer size mismatch" ); + + inline void RunComputeShader( ID3D11DeviceContext* pContext, + ID3D11ComputeShader* shader, + ID3D11ShaderResourceView** pSRVs, + UINT srvCount, + ID3D11Buffer* pCB, + ID3D11UnorderedAccessView* pUAV, + UINT X ) + { + // Force UAV to nullptr before setting SRV since we are swapping buffers + ID3D11UnorderedAccessView* nullUAV = nullptr; + pContext->CSSetUnorderedAccessViews( 0, 1, &nullUAV, nullptr ); + + pContext->CSSetShader( shader, nullptr, 0 ); + pContext->CSSetShaderResources( 0, srvCount, pSRVs ); + pContext->CSSetUnorderedAccessViews( 0, 1, &pUAV, nullptr ); + pContext->CSSetConstantBuffers( 0, 1, &pCB ); + pContext->Dispatch( X, 1, 1 ); + } + + inline void ResetContext( ID3D11DeviceContext* pContext ) + { + ID3D11UnorderedAccessView* nullUAV = nullptr; + pContext->CSSetUnorderedAccessViews( 0, 1, &nullUAV, nullptr ); + + ID3D11ShaderResourceView* nullSRV[3] = { nullptr, nullptr, nullptr }; + pContext->CSSetShaderResources( 0, 3, nullSRV ); + + ID3D11Buffer* nullBuffer[1] = { nullptr }; + pContext->CSSetConstantBuffers( 0, 1, nullBuffer ); + } +}; + +GPUCompressBC::GPUCompressBC() : + m_bcformat(DXGI_FORMAT_UNKNOWN), + m_srcformat(DXGI_FORMAT_UNKNOWN), + m_alphaWeight(1.f), + m_width(0), + m_height(0) +{ +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT GPUCompressBC::Initialize(ID3D11Device* pDevice) +{ + if (!pDevice) + return E_INVALIDARG; + + // Check for DirectCompute support + D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel(); + + if (fl < D3D_FEATURE_LEVEL_10_0) + { + // DirectCompute not supported on Feature Level 9.x hardware + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (fl < D3D_FEATURE_LEVEL_11_0) + { + // DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts; + HRESULT hr = pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts)); + if (FAILED(hr)) + { + memset(&hwopts, 0, sizeof(hwopts)); + } + + if (!hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + + // Save a device reference and obtain immediate context + m_device = pDevice; + + pDevice->GetImmediateContext(m_context.ReleaseAndGetAddressOf()); + assert(m_context); + + //--- Create compute shader library: BC6H ----------------------------------------- + + // Modes 11-14 + HRESULT hr = pDevice->CreateComputeShader(BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + // Modes 1-10 + hr = pDevice->CreateComputeShader(BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + // Encode + hr = pDevice->CreateComputeShader(BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + //--- Create compute shader library: BC7 ------------------------------------------ + + // Modes 4, 5, 6 + hr = pDevice->CreateComputeShader(BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + // Modes 1, 3, 7 + hr = pDevice->CreateComputeShader(BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + // Modes 0, 2 + hr = pDevice->CreateComputeShader(BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + // Encode + hr = pDevice->CreateComputeShader(BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + return hr; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT GPUCompressBC::Prepare(size_t width, size_t height, DWORD flags, DXGI_FORMAT format, float alphaWeight) +{ + if (!width || !height || alphaWeight < 0.f) + return E_INVALIDARG; + + if ((width > UINT32_MAX) || (height > UINT32_MAX)) + return E_INVALIDARG; + + m_width = width; + m_height = height; + + m_alphaWeight = alphaWeight; + + if (flags & TEX_COMPRESS_BC7_QUICK) + { + m_bc7_mode02 = false; + m_bc7_mode137 = false; + } + else + { + m_bc7_mode02 = (flags & TEX_COMPRESS_BC7_USE_3SUBSETS) != 0; + m_bc7_mode137 = true; + } + + size_t xblocks = std::max(1, (width + 3) >> 2); + size_t yblocks = std::max(1, (height + 3) >> 2); + size_t num_blocks = xblocks * yblocks; + + switch (format) + { + // BC6H GPU compressor takes RGBAF32 as input + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + m_srcformat = DXGI_FORMAT_R32G32B32A32_FLOAT; + break; + + // BC7 GPU compressor takes RGBA32 as input + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + + case DXGI_FORMAT_BC7_UNORM_SRGB: + m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + break; + + default: + m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + m_bcformat = format; + + auto pDevice = m_device.Get(); + if (!pDevice) + return E_POINTER; + + // Create structured buffers + size_t bufferSize = num_blocks * sizeof(BufferBC6HBC7); + { + D3D11_BUFFER_DESC desc = {}; + desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + desc.StructureByteStride = sizeof(BufferBC6HBC7); + desc.ByteWidth = static_cast(bufferSize); + + HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_output.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + + hr = pDevice->CreateBuffer(&desc, nullptr, m_err1.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + + hr = pDevice->CreateBuffer(&desc, nullptr, m_err2.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + // Create staging output buffer + { + D3D11_BUFFER_DESC desc = {}; + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.ByteWidth = static_cast(bufferSize); + + HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + // Create constant buffer + { + D3D11_BUFFER_DESC desc = {}; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.ByteWidth = sizeof(ConstantsBC6HBC7); + + HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + // Create shader resource views + { + D3D11_SHADER_RESOURCE_VIEW_DESC desc = {}; + desc.Buffer.NumElements = static_cast(num_blocks); + desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + HRESULT hr = pDevice->CreateShaderResourceView(m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + + hr = pDevice->CreateShaderResourceView(m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + // Create unordered access views + { + D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {}; + desc.Buffer.NumElements = static_cast(num_blocks); + desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + HRESULT hr = pDevice->CreateUnorderedAccessView(m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + + hr = pDevice->CreateUnorderedAccessView(m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + + hr = pDevice->CreateUnorderedAccessView(m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT GPUCompressBC::Compress(const Image& srcImage, const Image& destImage) +{ + if (!srcImage.pixels || !destImage.pixels) + return E_INVALIDARG; + + if (srcImage.width != destImage.width + || srcImage.height != destImage.height + || srcImage.width != m_width + || srcImage.height != m_height + || srcImage.format != m_srcformat + || destImage.format != m_bcformat) + { + return E_UNEXPECTED; + } + + //--- Create input texture -------------------------------------------------------- + auto pDevice = m_device.Get(); + if (!pDevice) + return E_POINTER; + + // We need to avoid the hardware doing additional colorspace conversion + DXGI_FORMAT inputFormat = (m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat; + + ComPtr sourceTex; + { + D3D11_TEXTURE2D_DESC desc = {}; + desc.Width = static_cast(srcImage.width); + desc.Height = static_cast(srcImage.height); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = inputFormat; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = srcImage.pixels; + initData.SysMemPitch = static_cast(srcImage.rowPitch); + initData.SysMemSlicePitch = static_cast(srcImage.slicePitch); + + HRESULT hr = pDevice->CreateTexture2D(&desc, &initData, sourceTex.GetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + ComPtr sourceSRV; + { + D3D11_SHADER_RESOURCE_VIEW_DESC desc = {}; + desc.Texture2D.MipLevels = 1; + desc.Format = inputFormat; + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + + HRESULT hr = pDevice->CreateShaderResourceView(sourceTex.Get(), &desc, sourceSRV.GetAddressOf()); + if (FAILED(hr)) + { + return hr; + } + } + + //--- Compress using DirectCompute ------------------------------------------------ + bool isbc7 = false; + switch (m_bcformat) + { + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + break; + + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + isbc7 = true; + break; + + default: + return E_UNEXPECTED; + } + + const UINT MAX_BLOCK_BATCH = 64; + + auto pContext = m_context.Get(); + if (!pContext) + return E_UNEXPECTED; + + size_t xblocks = std::max(1, (m_width + 3) >> 2); + size_t yblocks = std::max(1, (m_height + 3) >> 2); + + UINT num_total_blocks = static_cast(xblocks * yblocks); + UINT num_blocks = num_total_blocks; + int start_block_id = 0; + while (num_blocks > 0) + { + UINT n = std::min(num_blocks, MAX_BLOCK_BATCH); + UINT uThreadGroupCount = n; + + { + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); + if (FAILED(hr)) + return hr; + + ConstantsBC6HBC7 param; + param.tex_width = static_cast(srcImage.width); + param.num_block_x = static_cast(xblocks); + param.format = m_bcformat; + param.mode_id = 0; + param.start_block_id = start_block_id; + param.num_total_blocks = num_total_blocks; + param.alpha_weight = m_alphaWeight; + memcpy(mapped.pData, ¶m, sizeof(param)); + + pContext->Unmap(m_constBuffer.Get(), 0); + } + + if (isbc7) + { + //--- BC7 ----------------------------------------------------------------- + ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr }; + RunComputeShader(pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(), + m_err1UAV.Get(), std::max((uThreadGroupCount + 3) / 4, 1)); + + if (m_bc7_mode137) + { + for (UINT i = 0; i < 3; ++i) + { + static const UINT modes[] = { 1, 3, 7 }; + + // Mode 1: err1 -> err2 + // Mode 3: err2 -> err1 + // Mode 7: err1 -> err2 + { + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); + if (FAILED(hr)) + { + ResetContext(pContext); + return hr; + } + + ConstantsBC6HBC7 param; + param.tex_width = static_cast(srcImage.width); + param.num_block_x = static_cast(xblocks); + param.format = m_bcformat; + param.mode_id = modes[i]; + param.start_block_id = start_block_id; + param.num_total_blocks = num_total_blocks; + param.alpha_weight = m_alphaWeight; + memcpy(mapped.pData, ¶m, sizeof(param)); + pContext->Unmap(m_constBuffer.Get(), 0); + } + + pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get(); + RunComputeShader(pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(), + (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount); + } + } + + if (m_bc7_mode02) + { + // 3 subset modes tend to be used rarely and add significant compression time + for (UINT i = 0; i < 2; ++i) + { + static const UINT modes[] = { 0, 2 }; + // Mode 0: err2 -> err1 + // Mode 2: err1 -> err2 + { + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); + if (FAILED(hr)) + { + ResetContext(pContext); + return hr; + } + + ConstantsBC6HBC7 param; + param.tex_width = static_cast(srcImage.width); + param.num_block_x = static_cast(xblocks); + param.format = m_bcformat; + param.mode_id = modes[i]; + param.start_block_id = start_block_id; + param.num_total_blocks = num_total_blocks; + param.alpha_weight = m_alphaWeight; + memcpy(mapped.pData, ¶m, sizeof(param)); + pContext->Unmap(m_constBuffer.Get(), 0); + } + + pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get(); + RunComputeShader(pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(), + (i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount); + } + } + + pSRVs[1] = (m_bc7_mode02 || m_bc7_mode137) ? m_err2SRV.Get() : m_err1SRV.Get(); + RunComputeShader(pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(), + m_outputUAV.Get(), std::max((uThreadGroupCount + 3) / 4, 1)); + } + else + { + //--- BC6H ---------------------------------------------------------------- + ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr }; + RunComputeShader(pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(), + m_err1UAV.Get(), std::max((uThreadGroupCount + 3) / 4, 1)); + + for (UINT i = 0; i < 10; ++i) + { + { + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); + if (FAILED(hr)) + { + ResetContext(pContext); + return hr; + } + + ConstantsBC6HBC7 param; + param.tex_width = static_cast(srcImage.width); + param.num_block_x = static_cast(xblocks); + param.format = m_bcformat; + param.mode_id = i; + param.start_block_id = start_block_id; + param.num_total_blocks = num_total_blocks; + memcpy(mapped.pData, ¶m, sizeof(param)); + pContext->Unmap(m_constBuffer.Get(), 0); + } + + pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get(); + RunComputeShader(pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(), + (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max((uThreadGroupCount + 1) / 2, 1)); + } + + pSRVs[1] = m_err1SRV.Get(); + RunComputeShader(pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(), + m_outputUAV.Get(), std::max((uThreadGroupCount + 1) / 2, 1)); + } + + start_block_id += n; + num_blocks -= n; + } + + ResetContext(pContext); + + //--- Copy output texture back to CPU --------------------------------------------- + + pContext->CopyResource(m_outputCPU.Get(), m_output.Get()); + + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped); + if (SUCCEEDED(hr)) + { + const uint8_t *pSrc = reinterpret_cast(mapped.pData); + uint8_t *pDest = destImage.pixels; + + size_t pitch = xblocks * sizeof(BufferBC6HBC7); + + size_t rows = std::max(1, (destImage.height + 3) >> 2); + + for (size_t h = 0; h < rows; ++h) + { + memcpy(pDest, pSrc, destImage.rowPitch); + + pSrc += pitch; + pDest += destImage.rowPitch; + } + + pContext->Unmap(m_outputCPU.Get(), 0); + } + + return hr; +} \ No newline at end of file diff --git a/Kits/DirectXTex/BCDirectCompute.h b/Kits/DirectXTex/BCDirectCompute.h new file mode 100644 index 0000000000000000000000000000000000000000..bedc98231a88689ae2630070d37c31908bcbc6a0 --- /dev/null +++ b/Kits/DirectXTex/BCDirectCompute.h @@ -0,0 +1,68 @@ +//------------------------------------------------------------------------------------- +// BCDirectCompute.h +// +// Direct3D 11 Compute Shader BC Compressor +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +namespace DirectX +{ + +class GPUCompressBC +{ +public: + GPUCompressBC(); + + HRESULT Initialize( _In_ ID3D11Device* pDevice ); + + HRESULT Prepare( size_t width, size_t height, DWORD flags, DXGI_FORMAT format, float alphaWeight ); + + HRESULT Compress( const Image& srcImage, const Image& destImage ); + + DXGI_FORMAT GetSourceFormat() const { return m_srcformat; } + +private: + DXGI_FORMAT m_bcformat; + DXGI_FORMAT m_srcformat; + float m_alphaWeight; + bool m_bc7_mode02; + bool m_bc7_mode137; + size_t m_width; + size_t m_height; + + Microsoft::WRL::ComPtr m_device; + Microsoft::WRL::ComPtr m_context; + + Microsoft::WRL::ComPtr m_err1; + Microsoft::WRL::ComPtr m_err1UAV; + Microsoft::WRL::ComPtr m_err1SRV; + + Microsoft::WRL::ComPtr m_err2; + Microsoft::WRL::ComPtr m_err2UAV; + Microsoft::WRL::ComPtr m_err2SRV; + + Microsoft::WRL::ComPtr m_output; + Microsoft::WRL::ComPtr m_outputCPU; + Microsoft::WRL::ComPtr m_outputUAV; + Microsoft::WRL::ComPtr m_constBuffer; + + // Compute shader library + Microsoft::WRL::ComPtr m_BC6H_tryModeG10CS; + Microsoft::WRL::ComPtr m_BC6H_tryModeLE10CS; + Microsoft::WRL::ComPtr m_BC6H_encodeBlockCS; + + Microsoft::WRL::ComPtr m_BC7_tryMode456CS; + Microsoft::WRL::ComPtr m_BC7_tryMode137CS; + Microsoft::WRL::ComPtr m_BC7_tryMode02CS; + Microsoft::WRL::ComPtr m_BC7_encodeBlockCS; +}; + +}; // namespace \ No newline at end of file diff --git a/Kits/DirectXTex/DDS.h b/Kits/DirectXTex/DDS.h new file mode 100644 index 0000000000000000000000000000000000000000..9d85587be0e9b16fe2ff428df6320a30b0f6a4ac --- /dev/null +++ b/Kits/DirectXTex/DDS.h @@ -0,0 +1,247 @@ +//-------------------------------------------------------------------------------------- +// 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. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include + +namespace DirectX +{ + +#pragma pack(push,1) + +const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +struct DDS_PIXELFORMAT +{ + uint32_t dwSize; + uint32_t dwFlags; + uint32_t dwFourCC; + uint32_t dwRGBBitCount; + uint32_t dwRBitMask; + uint32_t dwGBitMask; + uint32_t dwBBitMask; + uint32_t 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_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 +#define DDS_PAL8A 0x00000021 // DDPF_PALETTEINDEXED8 | DDPF_ALPHAPIXELS +#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + +#ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ + ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 )) +#endif /* defined(MAKEFOURCC) */ + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8_ALT = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 8, 0x00ff, 0x0000, 0x0000, 0xff00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 = + { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V16U16 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue + +// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) +extern __declspec(selectany) 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 +enum DDS_RESOURCE_DIMENSION +{ + DDS_DIMENSION_TEXTURE1D = 2, + DDS_DIMENSION_TEXTURE2D = 3, + DDS_DIMENSION_TEXTURE3D = 4, +}; + +// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG +enum DDS_RESOURCE_MISC_FLAG +{ + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, +}; + +enum DDS_MISC_FLAGS2 +{ + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, +}; + +enum DDS_ALPHA_MODE +{ + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, +}; + +struct DDS_HEADER +{ + uint32_t dwSize; + uint32_t dwFlags; + uint32_t dwHeight; + uint32_t dwWidth; + uint32_t dwPitchOrLinearSize; + uint32_t dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags + uint32_t dwMipMapCount; + uint32_t dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t dwCaps; + uint32_t dwCaps2; + uint32_t dwCaps3; + uint32_t dwCaps4; + uint32_t dwReserved2; +}; + +struct DDS_HEADER_DXT10 +{ + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 +}; + +#pragma pack(pop) + +static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" ); +static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + +}; // namespace diff --git a/Kits/DirectXTex/DirectXTex.h b/Kits/DirectXTex/DirectXTex.h new file mode 100644 index 0000000000000000000000000000000000000000..f4a55d5f34e43f79ef0bc33edfc1c66888a0b16b --- /dev/null +++ b/Kits/DirectXTex/DirectXTex.h @@ -0,0 +1,709 @@ +//------------------------------------------------------------------------------------- +// DirectXTex.h +// +// DirectX Texture Library +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#pragma once + +#include + +#include +#include +#include + +#if !defined(__d3d11_h__) && !defined(__d3d11_x_h__) && !defined(__d3d12_h__) && !defined(__d3d12_x_h__) +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#define DCOMMON_H_INCLUDED +#else +#include +#endif +#endif + +#include + +#include + +#define DIRECTX_TEX_VERSION 151 + +struct IWICImagingFactory; +struct IWICMetadataQueryReader; + + +namespace DirectX +{ + + //--------------------------------------------------------------------------------- + // DXGI Format Utilities + bool __cdecl IsValid( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsCompressed( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsPacked( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsVideo( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsPlanar( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsPalettized( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsDepthStencil(_In_ DXGI_FORMAT fmt ); + bool __cdecl IsSRGB( _In_ DXGI_FORMAT fmt ); + bool __cdecl IsTypeless( _In_ DXGI_FORMAT fmt, _In_ bool partialTypeless = true ); + + bool __cdecl HasAlpha( _In_ DXGI_FORMAT fmt ); + + size_t __cdecl BitsPerPixel( _In_ DXGI_FORMAT fmt ); + + size_t __cdecl BitsPerColor( _In_ DXGI_FORMAT fmt ); + + enum CP_FLAGS + { + CP_FLAGS_NONE = 0x0, // Normal operation + CP_FLAGS_LEGACY_DWORD = 0x1, // Assume pitch is DWORD aligned instead of BYTE aligned + CP_FLAGS_PARAGRAPH = 0x2, // Assume pitch is 16-byte aligned instead of BYTE aligned + CP_FLAGS_YMM = 0x4, // Assume pitch is 32-byte aligned instead of BYTE aligned + CP_FLAGS_ZMM = 0x8, // Assume pitch is 64-byte aligned instead of BYTE aligned + CP_FLAGS_PAGE4K = 0x200, // Assume pitch is 4096-byte aligned instead of BYTE aligned + CP_FLAGS_BAD_DXTN_TAILS = 0x1000, // BC formats with malformed mipchain blocks smaller than 4x4 + CP_FLAGS_24BPP = 0x10000, // Override with a legacy 24 bits-per-pixel format size + CP_FLAGS_16BPP = 0x20000, // Override with a legacy 16 bits-per-pixel format size + CP_FLAGS_8BPP = 0x40000, // Override with a legacy 8 bits-per-pixel format size + }; + + void __cdecl ComputePitch( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, + _Out_ size_t& rowPitch, _Out_ size_t& slicePitch, _In_ DWORD flags = CP_FLAGS_NONE ); + + size_t __cdecl ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height ); + + DXGI_FORMAT __cdecl MakeSRGB( _In_ DXGI_FORMAT fmt ); + DXGI_FORMAT __cdecl MakeTypeless( _In_ DXGI_FORMAT fmt ); + DXGI_FORMAT __cdecl MakeTypelessUNORM( _In_ DXGI_FORMAT fmt ); + DXGI_FORMAT __cdecl MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt ); + + //--------------------------------------------------------------------------------- + // Texture metadata + enum TEX_DIMENSION + // Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION + { + TEX_DIMENSION_TEXTURE1D = 2, + TEX_DIMENSION_TEXTURE2D = 3, + TEX_DIMENSION_TEXTURE3D = 4, + }; + + enum TEX_MISC_FLAG + // Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG + { + TEX_MISC_TEXTURECUBE = 0x4L, + }; + + enum TEX_MISC_FLAG2 + { + TEX_MISC2_ALPHA_MODE_MASK = 0x7L, + }; + + enum TEX_ALPHA_MODE + // Matches DDS_ALPHA_MODE, encoded in MISC_FLAGS2 + { + TEX_ALPHA_MODE_UNKNOWN = 0, + TEX_ALPHA_MODE_STRAIGHT = 1, + TEX_ALPHA_MODE_PREMULTIPLIED = 2, + TEX_ALPHA_MODE_OPAQUE = 3, + TEX_ALPHA_MODE_CUSTOM = 4, + }; + + struct TexMetadata + { + size_t width; + size_t height; // Should be 1 for 1D textures + size_t depth; // Should be 1 for 1D or 2D textures + size_t arraySize; // For cubemap, this is a multiple of 6 + size_t mipLevels; + uint32_t miscFlags; + uint32_t miscFlags2; + DXGI_FORMAT format; + TEX_DIMENSION dimension; + + size_t __cdecl ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const; + // Returns size_t(-1) to indicate an out-of-range error + + bool __cdecl IsCubemap() const { return (miscFlags & TEX_MISC_TEXTURECUBE) != 0; } + // Helper for miscFlags + + bool __cdecl IsPMAlpha() const { return ((miscFlags2 & TEX_MISC2_ALPHA_MODE_MASK) == TEX_ALPHA_MODE_PREMULTIPLIED) != 0; } + void __cdecl SetAlphaMode( TEX_ALPHA_MODE mode ) { miscFlags2 = (miscFlags2 & ~TEX_MISC2_ALPHA_MODE_MASK) | static_cast(mode); } + TEX_ALPHA_MODE __cdecl GetAlphaMode() const { return static_cast(miscFlags2 & TEX_MISC2_ALPHA_MODE_MASK); } + // Helpers for miscFlags2 + + bool __cdecl IsVolumemap() const { return (dimension == TEX_DIMENSION_TEXTURE3D); } + // Helper for dimension + }; + + enum DDS_FLAGS + { + DDS_FLAGS_NONE = 0x0, + + DDS_FLAGS_LEGACY_DWORD = 0x1, + // Assume pitch is DWORD aligned instead of BYTE aligned (used by some legacy DDS files) + + DDS_FLAGS_NO_LEGACY_EXPANSION = 0x2, + // Do not implicitly convert legacy formats that result in larger pixel sizes (24 bpp, 3:3:2, A8L8, A4L4, P8, A8P8) + + DDS_FLAGS_NO_R10B10G10A2_FIXUP = 0x4, + // Do not use work-around for long-standing D3DX DDS file format issue which reversed the 10:10:10:2 color order masks + + DDS_FLAGS_FORCE_RGB = 0x8, + // Convert DXGI 1.1 BGR formats to DXGI_FORMAT_R8G8B8A8_UNORM to avoid use of optional WDDM 1.1 formats + + DDS_FLAGS_NO_16BPP = 0x10, + // Conversions avoid use of 565, 5551, and 4444 formats and instead expand to 8888 to avoid use of optional WDDM 1.2 formats + + DDS_FLAGS_EXPAND_LUMINANCE = 0x20, + // When loading legacy luminance formats expand replicating the color channels rather than leaving them packed (L8, L16, A8L8) + + DDS_FLAGS_BAD_DXTN_TAILS = 0x40, + // Some older DXTn DDS files incorrectly handle mipchain tails for blocks smaller than 4x4 + + DDS_FLAGS_FORCE_DX10_EXT = 0x10000, + // Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files) + + DDS_FLAGS_FORCE_DX10_EXT_MISC2 = 0x20000, + // DDS_FLAGS_FORCE_DX10_EXT including miscFlags2 information (result may not be compatible with D3DX10 or D3DX11) + }; + + enum WIC_FLAGS + { + WIC_FLAGS_NONE = 0x0, + + WIC_FLAGS_FORCE_RGB = 0x1, + // Loads DXGI 1.1 BGR formats as DXGI_FORMAT_R8G8B8A8_UNORM to avoid use of optional WDDM 1.1 formats + + WIC_FLAGS_NO_X2_BIAS = 0x2, + // Loads DXGI 1.1 X2 10:10:10:2 format as DXGI_FORMAT_R10G10B10A2_UNORM + + WIC_FLAGS_NO_16BPP = 0x4, + // Loads 565, 5551, and 4444 formats as 8888 to avoid use of optional WDDM 1.2 formats + + WIC_FLAGS_ALLOW_MONO = 0x8, + // Loads 1-bit monochrome (black & white) as R1_UNORM rather than 8-bit grayscale + + WIC_FLAGS_ALL_FRAMES = 0x10, + // Loads all images in a multi-frame file, converting/resizing to match the first frame as needed, defaults to 0th frame otherwise + + WIC_FLAGS_IGNORE_SRGB = 0x20, + // Ignores sRGB metadata if present in the file + + WIC_FLAGS_DITHER = 0x10000, + // Use ordered 4x4 dithering for any required conversions + + WIC_FLAGS_DITHER_DIFFUSION = 0x20000, + // Use error-diffusion dithering for any required conversions + + WIC_FLAGS_FILTER_POINT = 0x100000, + WIC_FLAGS_FILTER_LINEAR = 0x200000, + WIC_FLAGS_FILTER_CUBIC = 0x300000, + WIC_FLAGS_FILTER_FANT = 0x400000, // Combination of Linear and Box filter + // Filtering mode to use for any required image resizing (only needed when loading arrays of differently sized images; defaults to Fant) + }; + + HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags, + _Out_ TexMetadata& metadata ); + HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags, + _Out_ TexMetadata& metadata ); + + HRESULT __cdecl GetMetadataFromHDRMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, + _Out_ TexMetadata& metadata ); + HRESULT __cdecl GetMetadataFromHDRFile( _In_z_ const wchar_t* szFile, + _Out_ TexMetadata& metadata ); + + HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, + _Out_ TexMetadata& metadata ); + HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ const wchar_t* szFile, + _Out_ TexMetadata& metadata ); + + HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags, + _Out_ TexMetadata& metadata, + _In_opt_ std::function getMQR = nullptr); + + HRESULT __cdecl GetMetadataFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags, + _Out_ TexMetadata& metadata, + _In_opt_ std::function getMQR = nullptr); + + //--------------------------------------------------------------------------------- + // Bitmap image container + struct Image + { + size_t width; + size_t height; + DXGI_FORMAT format; + size_t rowPitch; + size_t slicePitch; + uint8_t* pixels; + }; + + class ScratchImage + { + public: + ScratchImage() + : m_nimages(0), m_size(0), m_metadata{}, m_image(nullptr), m_memory(nullptr) {} + ScratchImage(ScratchImage&& moveFrom) + : m_nimages(0), m_size(0), m_metadata{}, m_image(nullptr), m_memory(nullptr) { *this = std::move(moveFrom); } + ~ScratchImage() { Release(); } + + ScratchImage& __cdecl operator= (ScratchImage&& moveFrom); + + ScratchImage(const ScratchImage&) = delete; + ScratchImage& operator=(const ScratchImage&) = delete; + + HRESULT __cdecl Initialize( _In_ const TexMetadata& mdata, _In_ DWORD flags = CP_FLAGS_NONE ); + + HRESULT __cdecl Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE ); + HRESULT __cdecl Initialize2D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE ); + HRESULT __cdecl Initialize3D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t depth, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE ); + HRESULT __cdecl InitializeCube( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t nCubes, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE ); + + HRESULT __cdecl InitializeFromImage( _In_ const Image& srcImage, _In_ bool allow1D = false, _In_ DWORD flags = CP_FLAGS_NONE ); + HRESULT __cdecl InitializeArrayFromImages( _In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ bool allow1D = false, _In_ DWORD flags = CP_FLAGS_NONE ); + HRESULT __cdecl InitializeCubeFromImages( _In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ DWORD flags = CP_FLAGS_NONE ); + HRESULT __cdecl Initialize3DFromImages( _In_reads_(depth) const Image* images, _In_ size_t depth, _In_ DWORD flags = CP_FLAGS_NONE ); + + void __cdecl Release(); + + bool __cdecl OverrideFormat( _In_ DXGI_FORMAT f ); + + const TexMetadata& __cdecl GetMetadata() const { return m_metadata; } + const Image* __cdecl GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const; + + const Image* __cdecl GetImages() const { return m_image; } + size_t __cdecl GetImageCount() const { return m_nimages; } + + uint8_t* __cdecl GetPixels() const { return m_memory; } + size_t __cdecl GetPixelsSize() const { return m_size; } + + bool __cdecl IsAlphaAllOpaque() const; + + private: + size_t m_nimages; + size_t m_size; + TexMetadata m_metadata; + Image* m_image; + uint8_t* m_memory; + }; + + //--------------------------------------------------------------------------------- + // Memory blob (allocated buffer pointer is always 16-byte aligned) + class Blob + { + public: + Blob() : m_buffer(nullptr), m_size(0) {} + Blob(Blob&& moveFrom) : m_buffer(nullptr), m_size(0) { *this = std::move(moveFrom); } + ~Blob() { Release(); } + + Blob& __cdecl operator= (Blob&& moveFrom); + + Blob(const Blob&) = delete; + Blob& operator=(const Blob&) = delete; + + HRESULT __cdecl Initialize( _In_ size_t size ); + + void __cdecl Release(); + + void *__cdecl GetBufferPointer() const { return m_buffer; } + size_t __cdecl GetBufferSize() const { return m_size; } + + HRESULT __cdecl Trim(size_t size); + + private: + void* m_buffer; + size_t m_size; + }; + + //--------------------------------------------------------------------------------- + // Image I/O + + // DDS operations + HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + HRESULT __cdecl LoadFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + + HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags, + _Out_ Blob& blob ); + HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, + _Out_ Blob& blob ); + + HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ const wchar_t* szFile ); + HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ const wchar_t* szFile ); + + // HDR operations + HRESULT __cdecl LoadFromHDRMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + HRESULT __cdecl LoadFromHDRFile( _In_z_ const wchar_t* szFile, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + + HRESULT __cdecl SaveToHDRMemory( _In_ const Image& image, _Out_ Blob& blob ); + HRESULT __cdecl SaveToHDRFile( _In_ const Image& image, _In_z_ const wchar_t* szFile ); + + // TGA operations + HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + HRESULT __cdecl LoadFromTGAFile( _In_z_ const wchar_t* szFile, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + + HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob ); + HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ const wchar_t* szFile ); + + // WIC operations + HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image, + _In_opt_ std::function getMQR = nullptr); + HRESULT __cdecl LoadFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image, + _In_opt_ std::function getMQR = nullptr); + + HRESULT __cdecl SaveToWICMemory( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat, + _Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr, + _In_opt_ std::function setCustomProps = nullptr ); + HRESULT __cdecl SaveToWICMemory( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat, + _Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr, + _In_opt_ std::function setCustomProps = nullptr ); + + HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat, + _In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr, + _In_opt_ std::function setCustomProps = nullptr ); + HRESULT __cdecl SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat, + _In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr, + _In_opt_ std::function setCustomProps = nullptr ); + + //--------------------------------------------------------------------------------- + // Texture conversion, resizing, mipmap generation, and block compression + + enum TEX_FR_FLAGS + { + TEX_FR_ROTATE0 = 0x0, + TEX_FR_ROTATE90 = 0x1, + TEX_FR_ROTATE180 = 0x2, + TEX_FR_ROTATE270 = 0x3, + TEX_FR_FLIP_HORIZONTAL = 0x08, + TEX_FR_FLIP_VERTICAL = 0x10, + }; + + HRESULT __cdecl FlipRotate( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image ); + HRESULT __cdecl FlipRotate( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DWORD flags, _Out_ ScratchImage& result ); + // Flip and/or rotate image + + enum TEX_FILTER_FLAGS + { + TEX_FILTER_DEFAULT = 0, + + TEX_FILTER_WRAP_U = 0x1, + TEX_FILTER_WRAP_V = 0x2, + TEX_FILTER_WRAP_W = 0x4, + TEX_FILTER_WRAP = ( TEX_FILTER_WRAP_U | TEX_FILTER_WRAP_V | TEX_FILTER_WRAP_W ), + TEX_FILTER_MIRROR_U = 0x10, + TEX_FILTER_MIRROR_V = 0x20, + TEX_FILTER_MIRROR_W = 0x40, + TEX_FILTER_MIRROR = ( TEX_FILTER_MIRROR_U | TEX_FILTER_MIRROR_V | TEX_FILTER_MIRROR_W ), + // Wrap vs. Mirror vs. Clamp filtering options + + TEX_FILTER_SEPARATE_ALPHA = 0x100, + // Resize color and alpha channel independently + + TEX_FILTER_FLOAT_X2BIAS = 0x200, + // Enable *2 - 1 conversion cases for unorm<->float and positive-only float formats + + TEX_FILTER_RGB_COPY_RED = 0x1000, + TEX_FILTER_RGB_COPY_GREEN = 0x2000, + TEX_FILTER_RGB_COPY_BLUE = 0x4000, + // When converting RGB to R, defaults to using grayscale. These flags indicate copying a specific channel instead + // When converting RGB to RG, defaults to copying RED | GREEN. These flags control which channels are selected instead. + + TEX_FILTER_DITHER = 0x10000, + // Use ordered 4x4 dithering for any required conversions + TEX_FILTER_DITHER_DIFFUSION = 0x20000, + // Use error-diffusion dithering for any required conversions + + TEX_FILTER_POINT = 0x100000, + TEX_FILTER_LINEAR = 0x200000, + TEX_FILTER_CUBIC = 0x300000, + TEX_FILTER_BOX = 0x400000, + TEX_FILTER_FANT = 0x400000, // Equiv to Box filtering for mipmap generation + TEX_FILTER_TRIANGLE = 0x500000, + // Filtering mode to use for any required image resizing + + TEX_FILTER_SRGB_IN = 0x1000000, + TEX_FILTER_SRGB_OUT = 0x2000000, + TEX_FILTER_SRGB = ( TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT ), + // sRGB <-> RGB for use in conversion operations + // if the input format type is IsSRGB(), then SRGB_IN is on by default + // if the output format type is IsSRGB(), then SRGB_OUT is on by default + + TEX_FILTER_FORCE_NON_WIC = 0x10000000, + // Forces use of the non-WIC path when both are an option + + TEX_FILTER_FORCE_WIC = 0x20000000, + // Forces use of the WIC path even when logic would have picked a non-WIC path when both are an option + }; + + HRESULT __cdecl Resize( _In_ const Image& srcImage, _In_ size_t width, _In_ size_t height, _In_ DWORD filter, + _Out_ ScratchImage& image ); + HRESULT __cdecl Resize( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ size_t width, _In_ size_t height, _In_ DWORD filter, _Out_ ScratchImage& result ); + // Resize the image to width x height. Defaults to Fant filtering. + // Note for a complex resize, the result will always have mipLevels == 1 + + const float TEX_THRESHOLD_DEFAULT = 0.5f; + // Default value for alpha threshold used when converting to 1-bit alpha + + HRESULT __cdecl Convert( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, + _Out_ ScratchImage& image ); + HRESULT __cdecl Convert( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage& result ); + // Convert the image to a new format + + HRESULT __cdecl ConvertToSinglePlane( _In_ const Image& srcImage, _Out_ ScratchImage& image ); + HRESULT __cdecl ConvertToSinglePlane( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _Out_ ScratchImage& image ); + // Converts the image from a planar format to an equivalent non-planar format + + HRESULT __cdecl GenerateMipMaps( _In_ const Image& baseImage, _In_ DWORD filter, _In_ size_t levels, + _Inout_ ScratchImage& mipChain, _In_ bool allow1D = false ); + HRESULT __cdecl GenerateMipMaps( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DWORD filter, _In_ size_t levels, _Inout_ ScratchImage& mipChain ); + // levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image) + // Defaults to Fant filtering which is equivalent to a box filter + + HRESULT __cdecl GenerateMipMaps3D( _In_reads_(depth) const Image* baseImages, _In_ size_t depth, _In_ DWORD filter, _In_ size_t levels, + _Out_ ScratchImage& mipChain ); + HRESULT __cdecl GenerateMipMaps3D( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DWORD filter, _In_ size_t levels, _Out_ ScratchImage& mipChain ); + // levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image) + // Defaults to Fant filtering which is equivalent to a box filter + + enum TEX_PMALPHA_FLAGS + { + TEX_PMALPHA_DEFAULT = 0, + + TEX_PMALPHA_IGNORE_SRGB = 0x1, + // ignores sRGB colorspace conversions + + TEX_PMALPHA_REVERSE = 0x2, + // converts from premultiplied alpha back to straight alpha + + TEX_PMALPHA_SRGB_IN = 0x1000000, + TEX_PMALPHA_SRGB_OUT = 0x2000000, + TEX_PMALPHA_SRGB = ( TEX_PMALPHA_SRGB_IN | TEX_PMALPHA_SRGB_OUT ), + // if the input format type is IsSRGB(), then SRGB_IN is on by default + // if the output format type is IsSRGB(), then SRGB_OUT is on by default + }; + + HRESULT __cdecl PremultiplyAlpha( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image ); + HRESULT __cdecl PremultiplyAlpha( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DWORD flags, _Out_ ScratchImage& result ); + // Converts to/from a premultiplied alpha version of the texture + + enum TEX_COMPRESS_FLAGS + { + TEX_COMPRESS_DEFAULT = 0, + + TEX_COMPRESS_RGB_DITHER = 0x10000, + // Enables dithering RGB colors for BC1-3 compression + + TEX_COMPRESS_A_DITHER = 0x20000, + // Enables dithering alpha for BC1-3 compression + + TEX_COMPRESS_DITHER = 0x30000, + // Enables both RGB and alpha dithering for BC1-3 compression + + TEX_COMPRESS_UNIFORM = 0x40000, + // Uniform color weighting for BC1-3 compression; by default uses perceptual weighting + + TEX_COMPRESS_BC7_USE_3SUBSETS = 0x80000, + // Enables exhaustive search for BC7 compress for mode 0 and 2; by default skips trying these modes + + TEX_COMPRESS_BC7_QUICK = 0x100000, + // Minimal modes (usually mode 6) for BC7 compression + + TEX_COMPRESS_SRGB_IN = 0x1000000, + TEX_COMPRESS_SRGB_OUT = 0x2000000, + TEX_COMPRESS_SRGB = ( TEX_COMPRESS_SRGB_IN | TEX_COMPRESS_SRGB_OUT ), + // if the input format type is IsSRGB(), then SRGB_IN is on by default + // if the output format type is IsSRGB(), then SRGB_OUT is on by default + + TEX_COMPRESS_PARALLEL = 0x10000000, + // Compress is free to use multithreading to improve performance (by default it does not use multithreading) + }; + + HRESULT __cdecl Compress( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float threshold, + _Out_ ScratchImage& cImage ); + HRESULT __cdecl Compress( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float threshold, _Out_ ScratchImage& cImages ); + // Note that threshold is only used by BC1. TEX_THRESHOLD_DEFAULT is a typical value to use + +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) + HRESULT __cdecl Compress( _In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, + _In_ float alphaWeight, _Out_ ScratchImage& image ); + HRESULT __cdecl Compress( _In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaWeight, _Out_ ScratchImage& cImages ); + // DirectCompute-based compression (alphaWeight is only used by BC7. 1.0 is the typical value to use) +#endif + + HRESULT __cdecl Decompress( _In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image ); + HRESULT __cdecl Decompress( _In_reads_(nimages) const Image* cImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DXGI_FORMAT format, _Out_ ScratchImage& images ); + + //--------------------------------------------------------------------------------- + // Normal map operations + + enum CNMAP_FLAGS + { + CNMAP_DEFAULT = 0, + + CNMAP_CHANNEL_RED = 0x1, + CNMAP_CHANNEL_GREEN = 0x2, + CNMAP_CHANNEL_BLUE = 0x3, + CNMAP_CHANNEL_ALPHA = 0x4, + CNMAP_CHANNEL_LUMINANCE = 0x5, + // Channel selection when evaluting color value for height + // Luminance is a combination of red, green, and blue + + CNMAP_MIRROR_U = 0x1000, + CNMAP_MIRROR_V = 0x2000, + CNMAP_MIRROR = 0x3000, + // Use mirror semantics for scanline references (defaults to wrap) + + CNMAP_INVERT_SIGN = 0x4000, + // Inverts normal sign + + CNMAP_COMPUTE_OCCLUSION = 0x8000, + // Computes a crude occlusion term stored in the alpha channel + }; + + HRESULT __cdecl ComputeNormalMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude, + _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMap ); + HRESULT __cdecl ComputeNormalMap( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DWORD flags, _In_ float amplitude, _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMaps ); + + //--------------------------------------------------------------------------------- + // Misc image operations + + struct Rect + { + size_t x; + size_t y; + size_t w; + size_t h; + + Rect() = default; + Rect( size_t _x, size_t _y, size_t _w, size_t _h ) : x(_x), y(_y), w(_w), h(_h) {} + }; + + HRESULT __cdecl CopyRectangle( _In_ const Image& srcImage, _In_ const Rect& srcRect, _In_ const Image& dstImage, + _In_ DWORD filter, _In_ size_t xOffset, _In_ size_t yOffset ); + + enum CMSE_FLAGS + { + CMSE_DEFAULT = 0, + + CMSE_IMAGE1_SRGB = 0x1, + CMSE_IMAGE2_SRGB = 0x2, + // Indicates that image needs gamma correction before comparision + + CMSE_IGNORE_RED = 0x10, + CMSE_IGNORE_GREEN = 0x20, + CMSE_IGNORE_BLUE = 0x40, + CMSE_IGNORE_ALPHA = 0x80, + // Ignore the channel when computing MSE + + CMSE_IMAGE1_X2_BIAS = 0x100, + CMSE_IMAGE2_X2_BIAS = 0x200, + // Indicates that image should be scaled and biased before comparison (i.e. UNORM -> SNORM) + }; + + HRESULT __cdecl ComputeMSE( _In_ const Image& image1, _In_ const Image& image2, _Out_ float& mse, _Out_writes_opt_(4) float* mseV, _In_ DWORD flags = 0 ); + + HRESULT __cdecl EvaluateImage( _In_ const Image& image, + _In_ std::function pixelFunc ); + HRESULT __cdecl EvaluateImage( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ std::function pixelFunc ); + + HRESULT __cdecl TransformImage( _In_ const Image& image, + _In_ std::function pixelFunc, + ScratchImage& result ); + HRESULT __cdecl TransformImage( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ std::function pixelFunc, + ScratchImage& result ); + + //--------------------------------------------------------------------------------- + // WIC utility code + + enum WICCodecs + { + WIC_CODEC_BMP = 1, // Windows Bitmap (.bmp) + WIC_CODEC_JPEG, // Joint Photographic Experts Group (.jpg, .jpeg) + WIC_CODEC_PNG, // Portable Network Graphics (.png) + WIC_CODEC_TIFF, // Tagged Image File Format (.tif, .tiff) + WIC_CODEC_GIF, // Graphics Interchange Format (.gif) + WIC_CODEC_WMP, // Windows Media Photo / HD Photo / JPEG XR (.hdp, .jxr, .wdp) + WIC_CODEC_ICO, // Windows Icon (.ico) + }; + + REFGUID __cdecl GetWICCodec(_In_ WICCodecs codec); + + IWICImagingFactory* __cdecl GetWICFactory( bool& iswic2 ); + void __cdecl SetWICFactory( _In_opt_ IWICImagingFactory* pWIC); + + //--------------------------------------------------------------------------------- + // Direct3D 11 functions +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) + bool __cdecl IsSupportedTexture( _In_ ID3D11Device* pDevice, _In_ const TexMetadata& metadata ); + + HRESULT __cdecl CreateTexture( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _Outptr_ ID3D11Resource** ppResource ); + + HRESULT __cdecl CreateShaderResourceView( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _Outptr_ ID3D11ShaderResourceView** ppSRV ); + + HRESULT __cdecl CreateTextureEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, + _Outptr_ ID3D11Resource** ppResource ); + + HRESULT __cdecl CreateShaderResourceViewEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, + _Outptr_ ID3D11ShaderResourceView** ppSRV ); + + HRESULT __cdecl CaptureTexture( _In_ ID3D11Device* pDevice, _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _Out_ ScratchImage& result ); +#endif + + //--------------------------------------------------------------------------------- + // Direct3D 12 functions +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) + bool __cdecl IsSupportedTexture( _In_ ID3D12Device* pDevice, _In_ const TexMetadata& metadata ); + + HRESULT __cdecl CreateTexture( _In_ ID3D12Device* pDevice, _In_ const TexMetadata& metadata, + _Outptr_ ID3D12Resource** ppResource ); + + HRESULT __cdecl CreateTextureEx( _In_ ID3D12Device* pDevice, _In_ const TexMetadata& metadata, + _In_ D3D12_RESOURCE_FLAGS resFlags, _In_ bool forceSRGB, + _Outptr_ ID3D12Resource** ppResource ); + + HRESULT __cdecl PrepareUpload( _In_ ID3D12Device* pDevice, + _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + std::vector& subresources ); + + HRESULT __cdecl CaptureTexture( _In_ ID3D12CommandQueue* pCommandQueue, _In_ ID3D12Resource* pSource, _In_ bool isCubeMap, + _Out_ ScratchImage& result, + _In_ D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET, + _In_ D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_RENDER_TARGET ); +#endif + +#include "DirectXTex.inl" + +}; // namespace diff --git a/Kits/DirectXTex/DirectXTex.inl b/Kits/DirectXTex/DirectXTex.inl new file mode 100644 index 0000000000000000000000000000000000000000..5173869b85225d025399899b716f262c548bcff1 --- /dev/null +++ b/Kits/DirectXTex/DirectXTex.inl @@ -0,0 +1,128 @@ +//------------------------------------------------------------------------------------- +// DirectXTex.inl +// +// DirectX Texture Library +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#pragma once + +//===================================================================================== +// DXGI Format Utilities +//===================================================================================== + +_Use_decl_annotations_ +inline bool __cdecl IsValid( DXGI_FORMAT fmt ) +{ + return ( static_cast(fmt) >= 1 && static_cast(fmt) <= 190 ); +} + +_Use_decl_annotations_ +inline bool __cdecl IsCompressed(DXGI_FORMAT fmt) +{ + switch ( fmt ) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + 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_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + 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 true; + + default: + return false; + } +} + +_Use_decl_annotations_ +inline bool __cdecl IsPalettized(DXGI_FORMAT fmt) +{ + switch( fmt ) + { + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + return true; + + default: + return false; + } +} + +_Use_decl_annotations_ +inline bool __cdecl IsSRGB(DXGI_FORMAT fmt) +{ + switch( fmt ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + + default: + return false; + } +} + + +//===================================================================================== +// Image I/O +//===================================================================================== +_Use_decl_annotations_ +inline HRESULT __cdecl SaveToDDSMemory(const Image& image, DWORD flags, Blob& blob) +{ + TexMetadata mdata = {}; + mdata.width = image.width; + mdata.height = image.height; + mdata.depth = 1; + mdata.arraySize = 1; + mdata.mipLevels = 1; + mdata.format = image.format; + mdata.dimension = TEX_DIMENSION_TEXTURE2D; + + return SaveToDDSMemory( &image, 1, mdata, flags, blob ); +} + +_Use_decl_annotations_ +inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, const wchar_t* szFile) +{ + TexMetadata mdata = {}; + mdata.width = image.width; + mdata.height = image.height; + mdata.depth = 1; + mdata.arraySize = 1; + mdata.mipLevels = 1; + mdata.format = image.format; + mdata.dimension = TEX_DIMENSION_TEXTURE2D; + + return SaveToDDSFile( &image, 1, mdata, flags, szFile ); +} diff --git a/Kits/DirectXTex/DirectXTexCompress.cpp b/Kits/DirectXTex/DirectXTexCompress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c25c548701123f3b13da4d3e5b589059acb28cf --- /dev/null +++ b/Kits/DirectXTex/DirectXTexCompress.cpp @@ -0,0 +1,855 @@ +//------------------------------------------------------------------------------------- +// DirectXTexCompress.cpp +// +// DirectX Texture Library - Texture compression +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#ifdef _OPENMP +#include +#pragma warning(disable : 4616 6993) +#endif + +#include "bc.h" + +using namespace DirectX; + +namespace +{ + inline DWORD GetBCFlags(_In_ DWORD compress) + { + static_assert(static_cast(TEX_COMPRESS_RGB_DITHER) == static_cast(BC_FLAGS_DITHER_RGB), "TEX_COMPRESS_* flags should match BC_FLAGS_*"); + static_assert(static_cast(TEX_COMPRESS_A_DITHER) == static_cast(BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*"); + static_assert(static_cast(TEX_COMPRESS_DITHER) == static_cast(BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*"); + static_assert(static_cast(TEX_COMPRESS_UNIFORM) == static_cast(BC_FLAGS_UNIFORM), "TEX_COMPRESS_* flags should match BC_FLAGS_*"); + static_assert(static_cast(TEX_COMPRESS_BC7_USE_3SUBSETS) == static_cast(BC_FLAGS_USE_3SUBSETS), "TEX_COMPRESS_* flags should match BC_FLAGS_*"); + static_assert(static_cast(TEX_COMPRESS_BC7_QUICK) == static_cast(BC_FLAGS_FORCE_BC7_MODE6), "TEX_COMPRESS_* flags should match BC_FLAGS_*"); + return (compress & (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A | BC_FLAGS_UNIFORM | BC_FLAGS_USE_3SUBSETS | BC_FLAGS_FORCE_BC7_MODE6)); + } + + inline DWORD GetSRGBFlags(_In_ DWORD compress) + { + static_assert(static_cast(TEX_COMPRESS_SRGB_IN) == static_cast(TEX_FILTER_SRGB_IN), "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_COMPRESS_SRGB_OUT) == static_cast(TEX_FILTER_SRGB_OUT), "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_COMPRESS_SRGB) == static_cast(TEX_FILTER_SRGB), "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*"); + return (compress & TEX_COMPRESS_SRGB); + } + + inline bool DetermineEncoderSettings(_In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags) + { + switch (format) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; cflags = 0; break; + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode = D3DXEncodeBC2; blocksize = 16; cflags = 0; break; + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode = D3DXEncodeBC3; blocksize = 16; cflags = 0; break; + case DXGI_FORMAT_BC4_UNORM: pfEncode = D3DXEncodeBC4U; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break; + case DXGI_FORMAT_BC4_SNORM: pfEncode = D3DXEncodeBC4S; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break; + case DXGI_FORMAT_BC5_UNORM: pfEncode = D3DXEncodeBC5U; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break; + case DXGI_FORMAT_BC5_SNORM: pfEncode = D3DXEncodeBC5S; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break; + case DXGI_FORMAT_BC6H_UF16: pfEncode = D3DXEncodeBC6HU; blocksize = 16; cflags = 0; break; + case DXGI_FORMAT_BC6H_SF16: pfEncode = D3DXEncodeBC6HS; blocksize = 16; cflags = 0; break; + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode = D3DXEncodeBC7; blocksize = 16; cflags = 0; break; + default: pfEncode = nullptr; blocksize = 0; cflags = 0; return false; + } + + return true; + } + + + //------------------------------------------------------------------------------------- + HRESULT CompressBC( + const Image& image, + const Image& result, + DWORD bcflags, + DWORD srgb, + float threshold) + { + if (!image.pixels || !result.pixels) + return E_POINTER; + + assert(image.width == result.width); + assert(image.height == result.height); + + const DXGI_FORMAT format = image.format; + size_t sbpp = BitsPerPixel(format); + if (!sbpp) + return E_FAIL; + + if (sbpp < 8) + { + // We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Round to bytes + sbpp = (sbpp + 7) / 8; + + uint8_t *pDest = result.pixels; + + // Determine BC format encoder + BC_ENCODE pfEncode; + size_t blocksize; + DWORD cflags; + if (!DetermineEncoderSettings(result.format, pfEncode, blocksize, cflags)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + __declspec(align(16)) XMVECTOR temp[16]; + const uint8_t *pSrc = image.pixels; + const uint8_t *pEnd = image.pixels + image.slicePitch; + const size_t rowPitch = image.rowPitch; + for (size_t h = 0; h < image.height; h += 4) + { + const uint8_t *sptr = pSrc; + uint8_t* dptr = pDest; + size_t ph = std::min(4, image.height - h); + size_t w = 0; + for (size_t count = 0; (count < result.rowPitch) && (w < image.width); count += blocksize, w += 4) + { + size_t pw = std::min(4, image.width - w); + assert(pw > 0 && ph > 0); + + ptrdiff_t bytesLeft = pEnd - sptr; + assert(bytesLeft > 0); + size_t bytesToRead = std::min(rowPitch, bytesLeft); + if (!_LoadScanline(&temp[0], pw, sptr, bytesToRead, format)) + return E_FAIL; + + if (ph > 1) + { + bytesToRead = std::min(rowPitch, bytesLeft - rowPitch); + if (!_LoadScanline(&temp[4], pw, sptr + rowPitch, bytesToRead, format)) + return E_FAIL; + + if (ph > 2) + { + bytesToRead = std::min(rowPitch, bytesLeft - rowPitch * 2); + if (!_LoadScanline(&temp[8], pw, sptr + rowPitch * 2, bytesToRead, format)) + return E_FAIL; + + if (ph > 3) + { + bytesToRead = std::min(rowPitch, bytesLeft - rowPitch * 3); + if (!_LoadScanline(&temp[12], pw, sptr + rowPitch * 3, bytesToRead, format)) + return E_FAIL; + } + } + } + + if (pw != 4 || ph != 4) + { + // Replicate pixels for partial block + static const size_t uSrc[] = { 0, 0, 0, 1 }; + + if (pw < 4) + { + for (size_t t = 0; t < ph && t < 4; ++t) + { + for (size_t s = pw; s < 4; ++s) + { +#pragma prefast(suppress: 26000, "PREFAST false positive") + temp[(t << 2) | s] = temp[(t << 2) | uSrc[s]]; + } + } + } + + if (ph < 4) + { + for (size_t t = ph; t < 4; ++t) + { + for (size_t s = 0; s < 4; ++s) + { +#pragma prefast(suppress: 26000, "PREFAST false positive") + temp[(t << 2) | s] = temp[(uSrc[t] << 2) | s]; + } + } + } + } + + _ConvertScanline(temp, 16, result.format, format, cflags | srgb); + + if (pfEncode) + pfEncode(dptr, temp, bcflags); + else + D3DXEncodeBC1(dptr, temp, threshold, bcflags); + + sptr += sbpp * 4; + dptr += blocksize; + } + + pSrc += rowPitch * 4; + pDest += result.rowPitch; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- +#ifdef _OPENMP + HRESULT CompressBC_Parallel( + const Image& image, + const Image& result, + DWORD bcflags, + DWORD srgb, + float threshold) + { + if (!image.pixels || !result.pixels) + return E_POINTER; + + assert(image.width == result.width); + assert(image.height == result.height); + + const DXGI_FORMAT format = image.format; + size_t sbpp = BitsPerPixel(format); + if (!sbpp) + return E_FAIL; + + if (sbpp < 8) + { + // We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Round to bytes + sbpp = (sbpp + 7) / 8; + + const uint8_t *pEnd = image.pixels + image.slicePitch; + + // Determine BC format encoder + BC_ENCODE pfEncode; + size_t blocksize; + DWORD cflags; + if (!DetermineEncoderSettings(result.format, pfEncode, blocksize, cflags)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + // Refactored version of loop to support parallel independance + const size_t nBlocks = std::max(1, (image.width + 3) / 4) * std::max(1, (image.height + 3) / 4); + + bool fail = false; + +#pragma omp parallel for + for (int nb = 0; nb < static_cast(nBlocks); ++nb) + { + int nbWidth = std::max(1, int((image.width + 3) / 4)); + + int y = nb / nbWidth; + int x = (nb - (y*nbWidth)) * 4; + y *= 4; + + assert((x >= 0) && (x < int(image.width))); + assert((y >= 0) && (y < int(image.height))); + + size_t rowPitch = image.rowPitch; + const uint8_t *pSrc = image.pixels + (y*rowPitch) + (x*sbpp); + + uint8_t *pDest = result.pixels + (nb*blocksize); + + size_t ph = std::min(4, image.height - y); + size_t pw = std::min(4, image.width - x); + assert(pw > 0 && ph > 0); + + ptrdiff_t bytesLeft = pEnd - pSrc; + assert(bytesLeft > 0); + size_t bytesToRead = std::min(rowPitch, bytesLeft); + + __declspec(align(16)) XMVECTOR temp[16]; + if (!_LoadScanline(&temp[0], pw, pSrc, bytesToRead, format)) + fail = true; + + if (ph > 1) + { + bytesToRead = std::min(rowPitch, bytesLeft - rowPitch); + if (!_LoadScanline(&temp[4], pw, pSrc + rowPitch, bytesToRead, format)) + fail = true; + + if (ph > 2) + { + bytesToRead = std::min(rowPitch, bytesLeft - rowPitch * 2); + if (!_LoadScanline(&temp[8], pw, pSrc + rowPitch * 2, bytesToRead, format)) + fail = true; + + if (ph > 3) + { + bytesToRead = std::min(rowPitch, bytesLeft - rowPitch * 3); + if (!_LoadScanline(&temp[12], pw, pSrc + rowPitch * 3, bytesToRead, format)) + fail = true; + } + } + } + + if (pw != 4 || ph != 4) + { + // Replicate pixels for partial block + static const size_t uSrc[] = { 0, 0, 0, 1 }; + + if (pw < 4) + { + for (size_t t = 0; t < ph && t < 4; ++t) + { + for (size_t s = pw; s < 4; ++s) + { + temp[(t << 2) | s] = temp[(t << 2) | uSrc[s]]; + } + } + } + + if (ph < 4) + { + for (size_t t = ph; t < 4; ++t) + { + for (size_t s = 0; s < 4; ++s) + { + temp[(t << 2) | s] = temp[(uSrc[t] << 2) | s]; + } + } + } + } + + _ConvertScanline(temp, 16, result.format, format, cflags | srgb); + + if (pfEncode) + pfEncode(pDest, temp, bcflags); + else + D3DXEncodeBC1(pDest, temp, threshold, bcflags); + } + + return (fail) ? E_FAIL : S_OK; + } +#endif // _OPENMP + + + //------------------------------------------------------------------------------------- + DXGI_FORMAT DefaultDecompress(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + return DXGI_FORMAT_R8_UNORM; + + case DXGI_FORMAT_BC4_SNORM: + return DXGI_FORMAT_R8_SNORM; + + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + return DXGI_FORMAT_R8G8_UNORM; + + case DXGI_FORMAT_BC5_SNORM: + return DXGI_FORMAT_R8G8_SNORM; + + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + // We could use DXGI_FORMAT_R32G32B32_FLOAT here since BC6H is always Alpha 1.0, + // but this format is more supported by viewers + return DXGI_FORMAT_R32G32B32A32_FLOAT; + + default: + return DXGI_FORMAT_UNKNOWN; + } + } + + + //------------------------------------------------------------------------------------- + HRESULT DecompressBC(_In_ const Image& cImage, _In_ const Image& result) + { + if (!cImage.pixels || !result.pixels) + return E_POINTER; + + assert(cImage.width == result.width); + assert(cImage.height == result.height); + + const DXGI_FORMAT format = result.format; + size_t dbpp = BitsPerPixel(format); + if (!dbpp) + return E_FAIL; + + if (dbpp < 8) + { + // We don't support decompressing to monochrome (DXGI_FORMAT_R1_UNORM) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Round to bytes + dbpp = (dbpp + 7) / 8; + + uint8_t *pDest = result.pixels; + if (!pDest) + return E_POINTER; + + // Promote "typeless" BC formats + DXGI_FORMAT cformat; + switch (cImage.format) + { + case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break; + case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break; + case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break; + case DXGI_FORMAT_BC4_TYPELESS: cformat = DXGI_FORMAT_BC4_UNORM; break; + case DXGI_FORMAT_BC5_TYPELESS: cformat = DXGI_FORMAT_BC5_UNORM; break; + case DXGI_FORMAT_BC6H_TYPELESS: cformat = DXGI_FORMAT_BC6H_UF16; break; + case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break; + default: cformat = cImage.format; break; + } + + // Determine BC format decoder + BC_DECODE pfDecode; + size_t sbpp; + switch (cformat) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break; + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break; + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break; + case DXGI_FORMAT_BC4_UNORM: pfDecode = D3DXDecodeBC4U; sbpp = 8; break; + case DXGI_FORMAT_BC4_SNORM: pfDecode = D3DXDecodeBC4S; sbpp = 8; break; + case DXGI_FORMAT_BC5_UNORM: pfDecode = D3DXDecodeBC5U; sbpp = 16; break; + case DXGI_FORMAT_BC5_SNORM: pfDecode = D3DXDecodeBC5S; sbpp = 16; break; + case DXGI_FORMAT_BC6H_UF16: pfDecode = D3DXDecodeBC6HU; sbpp = 16; break; + case DXGI_FORMAT_BC6H_SF16: pfDecode = D3DXDecodeBC6HS; sbpp = 16; break; + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break; + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + __declspec(align(16)) XMVECTOR temp[16]; + const uint8_t *pSrc = cImage.pixels; + const size_t rowPitch = result.rowPitch; + for (size_t h = 0; h < cImage.height; h += 4) + { + const uint8_t *sptr = pSrc; + uint8_t* dptr = pDest; + size_t ph = std::min(4, cImage.height - h); + size_t w = 0; + for (size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4) + { + pfDecode(temp, sptr); + _ConvertScanline(temp, 16, format, cformat, 0); + + size_t pw = std::min(4, cImage.width - w); + assert(pw > 0 && ph > 0); + + if (!_StoreScanline(dptr, rowPitch, format, &temp[0], pw)) + return E_FAIL; + + if (ph > 1) + { + if (!_StoreScanline(dptr + rowPitch, rowPitch, format, &temp[4], pw)) + return E_FAIL; + + if (ph > 2) + { + if (!_StoreScanline(dptr + rowPitch * 2, rowPitch, format, &temp[8], pw)) + return E_FAIL; + + if (ph > 3) + { + if (!_StoreScanline(dptr + rowPitch * 3, rowPitch, format, &temp[12], pw)) + return E_FAIL; + } + } + } + + sptr += sbpp; + dptr += dbpp * 4; + } + + pSrc += cImage.rowPitch; + pDest += rowPitch * 4; + } + + return S_OK; + } +} + +//------------------------------------------------------------------------------------- +namespace DirectX +{ + bool _IsAlphaAllOpaqueBC(_In_ const Image& cImage) + { + if (!cImage.pixels) + return false; + + // Promote "typeless" BC formats + DXGI_FORMAT cformat; + switch (cImage.format) + { + case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break; + case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break; + case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break; + case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break; + default: cformat = cImage.format; break; + } + + // Determine BC format decoder + BC_DECODE pfDecode; + size_t sbpp; + switch (cformat) + { + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break; + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break; + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break; + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break; + default: + // BC4, BC5, and BC6 don't have alpha channels + return false; + } + + // Scan blocks for non-opaque alpha + static const XMVECTORF32 threshold = { { { 0.99f, 0.99f, 0.99f, 0.99f } } }; + + __declspec(align(16)) XMVECTOR temp[16]; + const uint8_t *pPixels = cImage.pixels; + for (size_t h = 0; h < cImage.height; h += 4) + { + const uint8_t *ptr = pPixels; + size_t ph = std::min(4, cImage.height - h); + size_t w = 0; + for (size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4) + { + pfDecode(temp, ptr); + + size_t pw = std::min(4, cImage.width - w); + assert(pw > 0 && ph > 0); + + if (pw == 4 && ph == 4) + { + // Full blocks + for (size_t j = 0; j < 16; ++j) + { + XMVECTOR alpha = XMVectorSplatW(temp[j]); + if (XMVector4Less(alpha, threshold)) + return false; + } + } + else + { + // Handle partial blocks + for (size_t y = 0; y < ph; ++y) + { + for (size_t x = 0; x < pw; ++x) + { + XMVECTOR alpha = XMVectorSplatW(temp[y * 4 + x]); + if (XMVector4Less(alpha, threshold)) + return false; + } + } + } + + ptr += sbpp; + } + + pPixels += cImage.rowPitch; + } + + return true; + } +}; + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Compress( + const Image& srcImage, + DXGI_FORMAT format, + DWORD compress, + float threshold, + ScratchImage& image) +{ + if (IsCompressed(srcImage.format) || !IsCompressed(format)) + return E_INVALIDARG; + + if (IsTypeless(format) + || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + // Create compressed image + HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + // Compress single image + if (compress & TEX_COMPRESS_PARALLEL) + { +#ifndef _OPENMP + return E_NOTIMPL; +#else + hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold); +#endif // _OPENMP + } + else + { + hr = CompressBC(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold); + } + + if (FAILED(hr)) + image.Release(); + + return hr; +} + +_Use_decl_annotations_ +HRESULT DirectX::Compress( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DXGI_FORMAT format, + DWORD compress, + float threshold, + ScratchImage& cImages) +{ + if (!srcImages || !nimages) + return E_INVALIDARG; + + if (IsCompressed(metadata.format) || !IsCompressed(format)) + return E_INVALIDARG; + + if (IsTypeless(format) + || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + cImages.Release(); + + TexMetadata mdata2 = metadata; + mdata2.format = format; + HRESULT hr = cImages.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != cImages.GetImageCount()) + { + cImages.Release(); + return E_FAIL; + } + + const Image* dest = cImages.GetImages(); + if (!dest) + { + cImages.Release(); + return E_POINTER; + } + + for (size_t index = 0; index < nimages; ++index) + { + assert(dest[index].format == format); + + const Image& src = srcImages[index]; + + if (src.width != dest[index].width || src.height != dest[index].height) + { + cImages.Release(); + return E_FAIL; + } + + if ((compress & TEX_COMPRESS_PARALLEL)) + { +#ifndef _OPENMP + return E_NOTIMPL; +#else + if (compress & TEX_COMPRESS_PARALLEL) + { + hr = CompressBC_Parallel(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), threshold); + if (FAILED(hr)) + { + cImages.Release(); + return hr; + } + } +#endif // _OPENMP + } + else + { + hr = CompressBC(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), threshold); + if (FAILED(hr)) + { + cImages.Release(); + return hr; + } + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Decompression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Decompress( + const Image& cImage, + DXGI_FORMAT format, + ScratchImage& image) +{ + if (!IsCompressed(cImage.format) || IsCompressed(format)) + return E_INVALIDARG; + + if (format == DXGI_FORMAT_UNKNOWN) + { + // Pick a default decompressed format based on BC input format + format = DefaultDecompress(cImage.format); + if (format == DXGI_FORMAT_UNKNOWN) + { + // Input is not a compressed format + return E_INVALIDARG; + } + } + else + { + if (!IsValid(format)) + return E_INVALIDARG; + + if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Create decompressed image + HRESULT hr = image.Initialize2D(format, cImage.width, cImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + // Decompress single image + hr = DecompressBC(cImage, *img); + if (FAILED(hr)) + image.Release(); + + return hr; +} + +_Use_decl_annotations_ +HRESULT DirectX::Decompress( + const Image* cImages, + size_t nimages, + const TexMetadata& metadata, + DXGI_FORMAT format, + ScratchImage& images) +{ + if (!cImages || !nimages) + return E_INVALIDARG; + + if (!IsCompressed(metadata.format) || IsCompressed(format)) + return E_INVALIDARG; + + if (format == DXGI_FORMAT_UNKNOWN) + { + // Pick a default decompressed format based on BC input format + format = DefaultDecompress(cImages[0].format); + if (format == DXGI_FORMAT_UNKNOWN) + { + // Input is not a compressed format + return E_FAIL; + } + } + else + { + if (!IsValid(format)) + return E_INVALIDARG; + + if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + images.Release(); + + TexMetadata mdata2 = metadata; + mdata2.format = format; + HRESULT hr = images.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != images.GetImageCount()) + { + images.Release(); + return E_FAIL; + } + + const Image* dest = images.GetImages(); + if (!dest) + { + images.Release(); + return E_POINTER; + } + + for (size_t index = 0; index < nimages; ++index) + { + assert(dest[index].format == format); + + const Image& src = cImages[index]; + if (!IsCompressed(src.format)) + { + images.Release(); + return E_FAIL; + } + + if (src.width != dest[index].width || src.height != dest[index].height) + { + images.Release(); + return E_FAIL; + } + + hr = DecompressBC(src, dest[index]); + if (FAILED(hr)) + { + images.Release(); + return hr; + } + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexCompressGPU.cpp b/Kits/DirectXTex/DirectXTexCompressGPU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..076be2a36271ee9ec9cfa8f80b2a7c17448002e6 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexCompressGPU.cpp @@ -0,0 +1,425 @@ +//------------------------------------------------------------------------------------- +// DirectXTexCompressGPU.cpp +// +// DirectX Texture Library - DirectCompute-based texture compression +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "bcdirectcompute.h" + +using namespace DirectX; + +namespace +{ + inline DWORD GetSRGBFlags(_In_ DWORD compress) + { + static_assert(static_cast(TEX_COMPRESS_SRGB_IN) == static_cast(TEX_FILTER_SRGB_IN), "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_COMPRESS_SRGB_OUT) == static_cast(TEX_FILTER_SRGB_OUT), "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_COMPRESS_SRGB) == static_cast(TEX_FILTER_SRGB), "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*"); + return (compress & TEX_COMPRESS_SRGB); + } + + + //------------------------------------------------------------------------------------- + // Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed + //------------------------------------------------------------------------------------- + HRESULT ConvertToRGBA32( + const Image& srcImage, + ScratchImage& image, + bool srgb, + DWORD filter) + { + if (!srcImage.pixels) + return E_POINTER; + + DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM; + + HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + uint8_t* pDest = img->pixels; + if (!pDest) + { + image.Release(); + return E_POINTER; + } + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR) * srcImage.width), 16))); + if (!scanline) + { + image.Release(); + return E_OUTOFMEMORY; + } + + const uint8_t *pSrc = srcImage.pixels; + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format)) + { + image.Release(); + return E_FAIL; + } + + _ConvertScanline(scanline.get(), srcImage.width, format, srcImage.format, filter); + + if (!_StoreScanline(pDest, img->rowPitch, format, scanline.get(), srcImage.width)) + { + image.Release(); + return E_FAIL; + } + + pSrc += srcImage.rowPitch; + pDest += img->rowPitch; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed + //------------------------------------------------------------------------------------- + HRESULT ConvertToRGBAF32( + const Image& srcImage, + ScratchImage& image, + DWORD filter) + { + if (!srcImage.pixels) + return E_POINTER; + + HRESULT hr = image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + uint8_t* pDest = img->pixels; + if (!pDest) + { + image.Release(); + return E_POINTER; + } + + const uint8_t *pSrc = srcImage.pixels; + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(reinterpret_cast(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format)) + { + image.Release(); + return E_FAIL; + } + + _ConvertScanline(reinterpret_cast(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter); + + pSrc += srcImage.rowPitch; + pDest += img->rowPitch; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Compress using GPU, converting to the proper input format for the shader if needed + //------------------------------------------------------------------------------------- + inline HRESULT GPUCompress( + _In_ GPUCompressBC* gpubc, + const Image& srcImage, + const Image& destImage, + DWORD compress) + { + if (!gpubc) + return E_POINTER; + + assert(srcImage.pixels && destImage.pixels); + + DXGI_FORMAT format = gpubc->GetSourceFormat(); + + if (srcImage.format == format) + { + // Input is already in our required source format + return gpubc->Compress(srcImage, destImage); + } + else + { + // Convert format and then use as the source image + ScratchImage image; + HRESULT hr; + + DWORD srgb = GetSRGBFlags(compress); + + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + hr = ConvertToRGBA32(srcImage, image, false, srgb); + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + hr = ConvertToRGBA32(srcImage, image, true, srgb); + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + hr = ConvertToRGBAF32(srcImage, image, srgb); + break; + + default: + hr = E_UNEXPECTED; + break; + } + + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + return E_POINTER; + + return gpubc->Compress(*img, destImage); + } + } +}; + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Compression +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Compress( + ID3D11Device* pDevice, + const Image& srcImage, + DXGI_FORMAT format, + DWORD compress, + float alphaWeight, + ScratchImage& image) +{ + if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format)) + return E_INVALIDARG; + + if (IsTypeless(format) + || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + // Setup GPU compressor + std::unique_ptr gpubc(new (std::nothrow) GPUCompressBC); + if (!gpubc) + return E_OUTOFMEMORY; + + HRESULT hr = gpubc->Initialize(pDevice); + if (FAILED(hr)) + return hr; + + hr = gpubc->Prepare(srcImage.width, srcImage.height, compress, format, alphaWeight); + if (FAILED(hr)) + return hr; + + // Create workspace for result + hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + hr = GPUCompress(gpubc.get(), srcImage, *img, compress); + if (FAILED(hr)) + image.Release(); + + return hr; +} + +_Use_decl_annotations_ +HRESULT DirectX::Compress( + ID3D11Device* pDevice, + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DXGI_FORMAT format, + DWORD compress, + float alphaWeight, + ScratchImage& cImages) +{ + if (!pDevice || !srcImages || !nimages) + return E_INVALIDARG; + + if (IsCompressed(metadata.format) || !IsCompressed(format)) + return E_INVALIDARG; + + if (IsTypeless(format) + || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + cImages.Release(); + + // Setup GPU compressor + std::unique_ptr gpubc(new (std::nothrow) GPUCompressBC); + if (!gpubc) + return E_OUTOFMEMORY; + + HRESULT hr = gpubc->Initialize(pDevice); + if (FAILED(hr)) + return hr; + + // Create workspace for result + TexMetadata mdata2 = metadata; + mdata2.format = format; + hr = cImages.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != cImages.GetImageCount()) + { + cImages.Release(); + return E_FAIL; + } + + const Image* dest = cImages.GetImages(); + if (!dest) + { + cImages.Release(); + return E_POINTER; + } + + // Process images (ordered by size) + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + { + size_t w = metadata.width; + size_t h = metadata.height; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + hr = gpubc->Prepare(w, h, compress, format, alphaWeight); + if (FAILED(hr)) + { + cImages.Release(); + return hr; + } + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t index = metadata.ComputeIndex(level, item, 0); + if (index >= nimages) + { + cImages.Release(); + return E_FAIL; + } + + assert(dest[index].format == format); + + const Image& src = srcImages[index]; + + if (src.width != dest[index].width || src.height != dest[index].height) + { + cImages.Release(); + return E_FAIL; + } + + hr = GPUCompress(gpubc.get(), src, dest[index], compress); + if (FAILED(hr)) + { + cImages.Release(); + return hr; + } + } + + if (h > 1) + h >>= 1; + + if (w > 1) + w >>= 1; + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + size_t w = metadata.width; + size_t h = metadata.height; + size_t d = metadata.depth; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + hr = gpubc->Prepare(w, h, compress, format, alphaWeight); + if (FAILED(hr)) + { + cImages.Release(); + return hr; + } + + for (size_t slice = 0; slice < d; ++slice) + { + size_t index = metadata.ComputeIndex(level, 0, slice); + if (index >= nimages) + { + cImages.Release(); + return E_FAIL; + } + + assert(dest[index].format == format); + + const Image& src = srcImages[index]; + + if (src.width != dest[index].width || src.height != dest[index].height) + { + cImages.Release(); + return E_FAIL; + } + + hr = GPUCompress(gpubc.get(), src, dest[index], compress); + if (FAILED(hr)) + { + cImages.Release(); + return hr; + } + } + + if (h > 1) + h >>= 1; + + if (w > 1) + w >>= 1; + + if (d > 1) + d >>= 1; + } + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexConvert.cpp b/Kits/DirectXTex/DirectXTexConvert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b791556c7e37dbf0f3986d3897e26822fc503810 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexConvert.cpp @@ -0,0 +1,5025 @@ +//------------------------------------------------------------------------------------- +// DirectXTexConvert.cpp +// +// DirectX Texture Library - Image pixel format conversion +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +using namespace DirectX; +using namespace DirectX::PackedVector; +using Microsoft::WRL::ComPtr; + +namespace +{ + inline uint32_t FloatTo7e3(float Value) + { + uint32_t IValue = reinterpret_cast(&Value)[0]; + + if (IValue & 0x80000000U) + { + // Positive only + return 0; + } + else if (IValue > 0x41FF73FFU) + { + // The number is too large to be represented as a 7e3. Saturate. + return 0x3FFU; + } + else + { + if (IValue < 0x3E800000U) + { + // The number is too small to be represented as a normalized 7e3. + // Convert it to a denormalized value. + uint32_t Shift = 125U - (IValue >> 23U); + IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift; + } + else + { + // Rebias the exponent to represent the value as a normalized 7e3. + IValue += 0xC2000000U; + } + + return ((IValue + 0x7FFFU + ((IValue >> 16U) & 1U)) >> 16U) & 0x3FFU; + } + } + + inline float FloatFrom7e3(uint32_t Value) + { + uint32_t Mantissa = (uint32_t)(Value & 0x7F); + + uint32_t Exponent = (Value & 0x380); + if (Exponent != 0) // The value is normalized + { + Exponent = (uint32_t)((Value >> 7) & 0x7); + } + else if (Mantissa != 0) // The value is denormalized + { + // Normalize the value in the resulting float + Exponent = 1; + + do + { + Exponent--; + Mantissa <<= 1; + } while ((Mantissa & 0x80) == 0); + + Mantissa &= 0x7F; + } + else // The value is zero + { + Exponent = (uint32_t)-124; + } + + uint32_t Result = ((Exponent + 124) << 23) | // Exponent + (Mantissa << 16); // Mantissa + + return reinterpret_cast(&Result)[0]; + } + + inline uint32_t FloatTo6e4(float Value) + { + uint32_t IValue = reinterpret_cast(&Value)[0]; + + if (IValue & 0x80000000U) + { + // Positive only + return 0; + } + else if (IValue > 0x43FEFFFFU) + { + // The number is too large to be represented as a 6e4. Saturate. + return 0x3FFU; + } + else + { + if (IValue < 0x3C800000U) + { + // The number is too small to be represented as a normalized 6e4. + // Convert it to a denormalized value. + uint32_t Shift = 121U - (IValue >> 23U); + IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift; + } + else + { + // Rebias the exponent to represent the value as a normalized 6e4. + IValue += 0xC4000000U; + } + + return ((IValue + 0xFFFFU + ((IValue >> 17U) & 1U)) >> 17U) & 0x3FFU; + } + } + + inline float FloatFrom6e4(uint32_t Value) + { + uint32_t Mantissa = (uint32_t)(Value & 0x3F); + + uint32_t Exponent = (Value & 0x3C0); + if (Exponent != 0) // The value is normalized + { + Exponent = (uint32_t)((Value >> 6) & 0xF); + } + else if (Mantissa != 0) // The value is denormalized + { + // Normalize the value in the resulting float + Exponent = 1; + + do + { + Exponent--; + Mantissa <<= 1; + } while ((Mantissa & 0x40) == 0); + + Mantissa &= 0x3F; + } + else // The value is zero + { + Exponent = (uint32_t)-120; + } + + uint32_t Result = ((Exponent + 120) << 23) | // Exponent + (Mantissa << 17); // Mantissa + + return reinterpret_cast(&Result)[0]; + } + +#if DIRECTX_MATH_VERSION >= 310 +#define StoreFloat3SE XMStoreFloat3SE +#else + inline void XM_CALLCONV StoreFloat3SE(_Out_ XMFLOAT3SE* pDestination, DirectX::FXMVECTOR V) + { + assert(pDestination); + + DirectX::XMFLOAT3A tmp; + DirectX::XMStoreFloat3A(&tmp, V); + + static const float maxf9 = float(0x1FF << 7); + static const float minf9 = float(1.f / (1 << 16)); + + float x = (tmp.x >= 0.f) ? ((tmp.x > maxf9) ? maxf9 : tmp.x) : 0.f; + float y = (tmp.y >= 0.f) ? ((tmp.y > maxf9) ? maxf9 : tmp.y) : 0.f; + float z = (tmp.z >= 0.f) ? ((tmp.z > maxf9) ? maxf9 : tmp.z) : 0.f; + + const float max_xy = (x > y) ? x : y; + const float max_xyz = (max_xy > z) ? max_xy : z; + + const float maxColor = (max_xyz > minf9) ? max_xyz : minf9; + + union { float f; int32_t i; } fi; + fi.f = maxColor; + fi.i += 0x00004000; // round up leaving 9 bits in fraction (including assumed 1) + + // Fix applied from DirectXMath 3.10 + uint32_t exp = fi.i >> 23; + pDestination->e = exp - 0x6f; + + fi.i = 0x83000000 - (exp << 23); + float ScaleR = fi.f; + + pDestination->xm = static_cast(lroundf(x * ScaleR)); + pDestination->ym = static_cast(lroundf(y * ScaleR)); + pDestination->zm = static_cast(lroundf(z * ScaleR)); + } +#endif + + const XMVECTORF32 g_Grayscale = { { { 0.2125f, 0.7154f, 0.0721f, 0.0f } } }; + const XMVECTORF32 g_HalfMin = { { { -65504.f, -65504.f, -65504.f, -65504.f } } }; + const XMVECTORF32 g_HalfMax = { { { 65504.f, 65504.f, 65504.f, 65504.f } } }; + const XMVECTORF32 g_8BitBias = { { { 0.5f / 255.f, 0.5f / 255.f, 0.5f / 255.f, 0.5f / 255.f } } }; +} + +//------------------------------------------------------------------------------------- +// Copies an image row with optional clearing of alpha value to 1.0 +// (can be used in place as well) otherwise copies the image row unmodified. +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::_CopyScanline( + void* pDestination, + size_t outSize, + const void* pSource, + size_t inSize, + DXGI_FORMAT format, + DWORD flags) +{ + assert(pDestination && outSize > 0); + assert(pSource && inSize > 0); + assert(IsValid(format) && !IsPalettized(format)); + + if (flags & TEXP_SCANLINE_SETALPHA) + { + switch (static_cast(format)) + { + //----------------------------------------------------------------------------- + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + if (inSize >= 16 && outSize >= 16) + { + uint32_t alpha; + if (format == DXGI_FORMAT_R32G32B32A32_FLOAT) + alpha = 0x3f800000; + else if (format == DXGI_FORMAT_R32G32B32A32_SINT) + alpha = 0x7fffffff; + else + alpha = 0xffffffff; + + if (pDestination == pSource) + { + uint32_t *dPtr = reinterpret_cast (pDestination); + for (size_t count = 0; count < (outSize - 15); count += 16) + { + dPtr += 3; + *(dPtr++) = alpha; + } + } + else + { + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 15); count += 16) + { + *(dPtr++) = *(sPtr++); + *(dPtr++) = *(sPtr++); + *(dPtr++) = *(sPtr++); + *(dPtr++) = alpha; + ++sPtr; + } + } + } + return; + + //----------------------------------------------------------------------------- + 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_Y416: + if (inSize >= 8 && outSize >= 8) + { + uint16_t alpha; + if (format == DXGI_FORMAT_R16G16B16A16_FLOAT) + alpha = 0x3c00; + else if (format == DXGI_FORMAT_R16G16B16A16_SNORM || format == DXGI_FORMAT_R16G16B16A16_SINT) + alpha = 0x7fff; + else + alpha = 0xffff; + + if (pDestination == pSource) + { + uint16_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 7); count += 8) + { + dPtr += 3; + *(dPtr++) = alpha; + } + } + else + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 7); count += 8) + { + *(dPtr++) = *(sPtr++); + *(dPtr++) = *(sPtr++); + *(dPtr++) = *(sPtr++); + *(dPtr++) = alpha; + ++sPtr; + } + } + } + return; + + //----------------------------------------------------------------------------- + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_Y410: + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + if (inSize >= 4 && outSize >= 4) + { + if (pDestination == pSource) + { + uint32_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 3); count += 4) + { + *dPtr |= 0xC0000000; + ++dPtr; + } + } + else + { + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 3); count += 4) + { + *(dPtr++) = *(sPtr++) | 0xC0000000; + } + } + } + return; + + //----------------------------------------------------------------------------- + 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_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + if (inSize >= 4 && outSize >= 4) + { + const uint32_t alpha = (format == DXGI_FORMAT_R8G8B8A8_SNORM || format == DXGI_FORMAT_R8G8B8A8_SINT) ? 0x7f000000 : 0xff000000; + + if (pDestination == pSource) + { + uint32_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 3); count += 4) + { + uint32_t t = *dPtr & 0xFFFFFF; + t |= alpha; + *(dPtr++) = t; + } + } + else + { + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 3); count += 4) + { + uint32_t t = *(sPtr++) & 0xFFFFFF; + t |= alpha; + *(dPtr++) = t; + } + } + } + return; + + //----------------------------------------------------------------------------- + case DXGI_FORMAT_B5G5R5A1_UNORM: + if (inSize >= 2 && outSize >= 2) + { + if (pDestination == pSource) + { + uint16_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 1); count += 2) + { + *(dPtr++) |= 0x8000; + } + } + else + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 1); count += 2) + { + *(dPtr++) = *(sPtr++) | 0x8000; + } + } + } + return; + + //----------------------------------------------------------------------------- + case DXGI_FORMAT_A8_UNORM: + memset(pDestination, 0xff, outSize); + return; + + //----------------------------------------------------------------------------- + case DXGI_FORMAT_B4G4R4A4_UNORM: + if (inSize >= 2 && outSize >= 2) + { + if (pDestination == pSource) + { + uint16_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 1); count += 2) + { + *(dPtr++) |= 0xF000; + } + } + else + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 1); count += 2) + { + *(dPtr++) = *(sPtr++) | 0xF000; + } + } + } + return; + } + } + + // Fall-through case is to just use memcpy (assuming this is not an in-place operation) + if (pDestination == pSource) + return; + + size_t size = std::min(outSize, inSize); + memcpy_s(pDestination, outSize, pSource, size); +} + + +//------------------------------------------------------------------------------------- +// Swizzles (RGB <-> BGR) an image row with optional clearing of alpha value to 1.0 +// (can be used in place as well) otherwise copies the image row unmodified. +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::_SwizzleScanline( + void* pDestination, + size_t outSize, + const void* pSource, + size_t inSize, + DXGI_FORMAT format, + DWORD flags) +{ + assert(pDestination && outSize > 0); + assert(pSource && inSize > 0); + assert(IsValid(format) && !IsPlanar(format) && !IsPalettized(format)); + + switch (static_cast(format)) + { + //--------------------------------------------------------------------------------- + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + if (inSize >= 4 && outSize >= 4) + { + if (flags & TEXP_SCANLINE_LEGACY) + { + // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources) + if (pDestination == pSource) + { + uint32_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 3); count += 4) + { + uint32_t t = *dPtr; + + uint32_t t1 = (t & 0x3ff00000) >> 20; + uint32_t t2 = (t & 0x000003ff) << 20; + uint32_t t3 = (t & 0x000ffc00); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xC0000000 : (t & 0xC0000000); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + } + else + { + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 3); count += 4) + { + uint32_t t = *(sPtr++); + + uint32_t t1 = (t & 0x3ff00000) >> 20; + uint32_t t2 = (t & 0x000003ff) << 20; + uint32_t t3 = (t & 0x000ffc00); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xC0000000 : (t & 0xC0000000); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + } + return; + } + } + break; + + //--------------------------------------------------------------------------------- + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + if (inSize >= 4 && outSize >= 4) + { + // Swap Red (R) and Blue (B) channels (used to convert from DXGI 1.1 BGR formats to DXGI 1.0 RGB) + if (pDestination == pSource) + { + uint32_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 3); count += 4) + { + uint32_t t = *dPtr; + + uint32_t t1 = (t & 0x00ff0000) >> 16; + uint32_t t2 = (t & 0x000000ff) << 16; + uint32_t t3 = (t & 0x0000ff00); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (t & 0xFF000000); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + } + else + { + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 3); count += 4) + { + uint32_t t = *(sPtr++); + + uint32_t t1 = (t & 0x00ff0000) >> 16; + uint32_t t2 = (t & 0x000000ff) << 16; + uint32_t t3 = (t & 0x0000ff00); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (t & 0xFF000000); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + } + return; + } + break; + + //--------------------------------------------------------------------------------- + case DXGI_FORMAT_YUY2: + if (inSize >= 4 && outSize >= 4) + { + if (flags & TEXP_SCANLINE_LEGACY) + { + // Reorder YUV components (used to convert legacy UYVY -> YUY2) + if (pDestination == pSource) + { + uint32_t *dPtr = reinterpret_cast(pDestination); + for (size_t count = 0; count < (outSize - 3); count += 4) + { + uint32_t t = *dPtr; + + uint32_t t1 = (t & 0x000000ff) << 8; + uint32_t t2 = (t & 0x0000ff00) >> 8; + uint32_t t3 = (t & 0x00ff0000) << 8; + uint32_t t4 = (t & 0xff000000) >> 8; + + *(dPtr++) = t1 | t2 | t3 | t4; + } + } + else + { + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + size_t size = std::min(outSize, inSize); + for (size_t count = 0; count < (size - 3); count += 4) + { + uint32_t t = *(sPtr++); + + uint32_t t1 = (t & 0x000000ff) << 8; + uint32_t t2 = (t & 0x0000ff00) >> 8; + uint32_t t3 = (t & 0x00ff0000) << 8; + uint32_t t4 = (t & 0xff000000) >> 8; + + *(dPtr++) = t1 | t2 | t3 | t4; + } + } + return; + } + } + break; + } + + // Fall-through case is to just use memcpy (assuming this is not an in-place operation) + if (pDestination == pSource) + return; + + size_t size = std::min(outSize, inSize); + memcpy_s(pDestination, outSize, pSource, size); +} + + +//------------------------------------------------------------------------------------- +// Converts an image row with optional clearing of alpha value to 1.0 +// Returns true if supported, false if expansion case not supported +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::_ExpandScanline( + void* pDestination, + size_t outSize, + DXGI_FORMAT outFormat, + const void* pSource, + size_t inSize, + DXGI_FORMAT inFormat, + DWORD flags) +{ + assert(pDestination && outSize > 0); + assert(pSource && inSize > 0); + assert(IsValid(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat)); + assert(IsValid(inFormat) && !IsPlanar(inFormat) && !IsPalettized(inFormat)); + + switch (inFormat) + { + case DXGI_FORMAT_B5G6R5_UNORM: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // DXGI_FORMAT_B5G6R5_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = ((t & 0xf800) >> 8) | ((t & 0xe000) >> 13); + uint32_t t2 = ((t & 0x07e0) << 5) | ((t & 0x0600) >> 5); + uint32_t t3 = ((t & 0x001f) << 19) | ((t & 0x001c) << 14); + + *(dPtr++) = t1 | t2 | t3 | 0xff000000; + } + return true; + } + return false; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // DXGI_FORMAT_B5G5R5A1_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = ((t & 0x7c00) >> 7) | ((t & 0x7000) >> 12); + uint32_t t2 = ((t & 0x03e0) << 6) | ((t & 0x0380) << 1); + uint32_t t3 = ((t & 0x001f) << 19) | ((t & 0x001c) << 14); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : ((t & 0x8000) ? 0xff000000 : 0); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + return true; + } + return false; + + case DXGI_FORMAT_B4G4R4A4_UNORM: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // DXGI_FORMAT_B4G4R4A4_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = ((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8); + uint32_t t2 = ((t & 0x00f0) << 8) | ((t & 0x00f0) << 4); + uint32_t t3 = ((t & 0x000f) << 20) | ((t & 0x000f) << 16); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (((t & 0xf000) << 16) | ((t & 0xf000) << 12)); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + return true; + } + return false; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +// Loads an image row into standard RGBA XMVECTOR (aligned) array +//------------------------------------------------------------------------------------- +#define LOAD_SCANLINE( type, func )\ + if ( size >= sizeof(type) )\ + {\ + const type * __restrict sPtr = reinterpret_cast(pSource);\ + for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\ + {\ + if ( dPtr >= ePtr ) break;\ + *(dPtr++) = func( sPtr++ );\ + }\ + return true;\ + }\ + return false; + +#define LOAD_SCANLINE3( type, func, defvec )\ + if ( size >= sizeof(type) )\ + {\ + const type * __restrict sPtr = reinterpret_cast(pSource);\ + for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\ + {\ + XMVECTOR v = func( sPtr++ );\ + if ( dPtr >= ePtr ) break;\ + *(dPtr++) = XMVectorSelect( defvec, v, g_XMSelect1110 );\ + }\ + return true;\ + }\ + return false; + +#define LOAD_SCANLINE2( type, func, defvec )\ + if ( size >= sizeof(type) )\ + {\ + const type * __restrict sPtr = reinterpret_cast(pSource);\ + for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\ + {\ + XMVECTOR v = func( sPtr++ );\ + if ( dPtr >= ePtr ) break;\ + *(dPtr++) = XMVectorSelect( defvec, v, g_XMSelect1100 );\ + }\ + return true;\ + }\ + return false; + +#pragma warning(suppress: 6101) +_Use_decl_annotations_ bool DirectX::_LoadScanline( + XMVECTOR* pDestination, + size_t count, + const void* pSource, + size_t size, + DXGI_FORMAT format) +{ + assert(pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0)); + assert(pSource && size > 0); + assert(IsValid(format) && !IsTypeless(format, false) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format)); + + XMVECTOR* __restrict dPtr = pDestination; + if (!dPtr) + return false; + + const XMVECTOR* ePtr = pDestination + count; + + switch (static_cast(format)) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + size_t msize = (size > (sizeof(XMVECTOR)*count)) ? (sizeof(XMVECTOR)*count) : size; + memcpy_s(dPtr, sizeof(XMVECTOR)*count, pSource, msize); + } + return true; + + case DXGI_FORMAT_R32G32B32A32_UINT: + LOAD_SCANLINE(XMUINT4, XMLoadUInt4) + + case DXGI_FORMAT_R32G32B32A32_SINT: + LOAD_SCANLINE(XMINT4, XMLoadSInt4) + + case DXGI_FORMAT_R32G32B32_FLOAT: + LOAD_SCANLINE3(XMFLOAT3, XMLoadFloat3, g_XMIdentityR3) + + case DXGI_FORMAT_R32G32B32_UINT: + LOAD_SCANLINE3(XMUINT3, XMLoadUInt3, g_XMIdentityR3) + + case DXGI_FORMAT_R32G32B32_SINT: + LOAD_SCANLINE3(XMINT3, XMLoadSInt3, g_XMIdentityR3) + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + LOAD_SCANLINE(XMHALF4, XMLoadHalf4) + + case DXGI_FORMAT_R16G16B16A16_UNORM: + LOAD_SCANLINE(XMUSHORTN4, XMLoadUShortN4) + + case DXGI_FORMAT_R16G16B16A16_UINT: + LOAD_SCANLINE(XMUSHORT4, XMLoadUShort4) + + case DXGI_FORMAT_R16G16B16A16_SNORM: + LOAD_SCANLINE(XMSHORTN4, XMLoadShortN4) + + case DXGI_FORMAT_R16G16B16A16_SINT: + LOAD_SCANLINE(XMSHORT4, XMLoadShort4) + + case DXGI_FORMAT_R32G32_FLOAT: + LOAD_SCANLINE2(XMFLOAT2, XMLoadFloat2, g_XMIdentityR3) + + case DXGI_FORMAT_R32G32_UINT: + LOAD_SCANLINE2(XMUINT2, XMLoadUInt2, g_XMIdentityR3) + + case DXGI_FORMAT_R32G32_SINT: + LOAD_SCANLINE2(XMINT2, XMLoadSInt2, g_XMIdentityR3) + + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + const size_t psize = sizeof(float) + sizeof(uint32_t); + if (size >= psize) + { + const float * sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - psize + 1); icount += psize) + { + const uint8_t* ps8 = reinterpret_cast(&sPtr[1]); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(sPtr[0], static_cast(*ps8), 0.f, 1.f); + sPtr += 2; + } + return true; + } + } + return false; + + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + const size_t psize = sizeof(float) + sizeof(uint32_t); + if (size >= psize) + { + const float * sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - psize + 1); icount += psize) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(sPtr[0], 0.f /* typeless component assumed zero */, 0.f, 1.f); + sPtr += 2; + } + return true; + } + } + return false; + + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + const size_t psize = sizeof(float) + sizeof(uint32_t); + if (size >= psize) + { + const float * sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - psize + 1); icount += psize) + { + const uint8_t* pg8 = reinterpret_cast(&sPtr[1]); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(0.f /* typeless component assumed zero */, static_cast(*pg8), 0.f, 1.f); + sPtr += 2; + } + return true; + } + } + return false; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + LOAD_SCANLINE(XMUDECN4, XMLoadUDecN4); + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + LOAD_SCANLINE(XMUDECN4, XMLoadUDecN4_XR); + + case DXGI_FORMAT_R10G10B10A2_UINT: + LOAD_SCANLINE(XMUDEC4, XMLoadUDec4); + + case DXGI_FORMAT_R11G11B10_FLOAT: + LOAD_SCANLINE3(XMFLOAT3PK, XMLoadFloat3PK, g_XMIdentityR3); + + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + LOAD_SCANLINE(XMUBYTEN4, XMLoadUByteN4) + + case DXGI_FORMAT_R8G8B8A8_UINT: + LOAD_SCANLINE(XMUBYTE4, XMLoadUByte4) + + case DXGI_FORMAT_R8G8B8A8_SNORM: + LOAD_SCANLINE(XMBYTEN4, XMLoadByteN4) + + case DXGI_FORMAT_R8G8B8A8_SINT: + LOAD_SCANLINE(XMBYTE4, XMLoadByte4) + + case DXGI_FORMAT_R16G16_FLOAT: + LOAD_SCANLINE2(XMHALF2, XMLoadHalf2, g_XMIdentityR3) + + case DXGI_FORMAT_R16G16_UNORM: + LOAD_SCANLINE2(XMUSHORTN2, XMLoadUShortN2, g_XMIdentityR3) + + case DXGI_FORMAT_R16G16_UINT: + LOAD_SCANLINE2(XMUSHORT2, XMLoadUShort2, g_XMIdentityR3) + + case DXGI_FORMAT_R16G16_SNORM: + LOAD_SCANLINE2(XMSHORTN2, XMLoadShortN2, g_XMIdentityR3) + + case DXGI_FORMAT_R16G16_SINT: + LOAD_SCANLINE2(XMSHORT2, XMLoadShort2, g_XMIdentityR3) + + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + if (size >= sizeof(float)) + { + const float* __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(float) + 1); icount += sizeof(float)) + { + XMVECTOR v = XMLoadFloat(sPtr++); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1000); + } + return true; + } + return false; + + case DXGI_FORMAT_R32_UINT: + if (size >= sizeof(uint32_t)) + { + const uint32_t* __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint32_t) + 1); icount += sizeof(uint32_t)) + { + XMVECTOR v = XMLoadInt(sPtr++); + v = XMConvertVectorUIntToFloat(v, 0); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1000); + } + return true; + } + return false; + + case DXGI_FORMAT_R32_SINT: + if (size >= sizeof(int32_t)) + { + const int32_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(int32_t) + 1); icount += sizeof(int32_t)) + { + XMVECTOR v = XMLoadInt(reinterpret_cast (sPtr++)); + v = XMConvertVectorIntToFloat(v, 0); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1000); + } + return true; + } + return false; + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + if (size >= sizeof(uint32_t)) + { + const uint32_t * sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint32_t) + 1); icount += sizeof(uint32_t)) + { + float d = static_cast(*sPtr & 0xFFFFFF) / 16777215.f; + float s = static_cast((*sPtr & 0xFF000000) >> 24); + ++sPtr; + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(d, s, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + if (size >= sizeof(uint32_t)) + { + const uint32_t * sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint32_t) + 1); icount += sizeof(uint32_t)) + { + float r = static_cast(*sPtr & 0xFFFFFF) / 16777215.f; + ++sPtr; + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(r, 0.f /* typeless component assumed zero */, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + if (size >= sizeof(uint32_t)) + { + const uint32_t * sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint32_t) + 1); icount += sizeof(uint32_t)) + { + float g = static_cast((*sPtr & 0xFF000000) >> 24); + ++sPtr; + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(0.f /* typeless component assumed zero */, g, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8G8_UNORM: + LOAD_SCANLINE2(XMUBYTEN2, XMLoadUByteN2, g_XMIdentityR3) + + case DXGI_FORMAT_R8G8_UINT: + LOAD_SCANLINE2(XMUBYTE2, XMLoadUByte2, g_XMIdentityR3) + + case DXGI_FORMAT_R8G8_SNORM: + LOAD_SCANLINE2(XMBYTEN2, XMLoadByteN2, g_XMIdentityR3) + + case DXGI_FORMAT_R8G8_SINT: + LOAD_SCANLINE2(XMBYTE2, XMLoadByte2, g_XMIdentityR3) + + case DXGI_FORMAT_R16_FLOAT: + if (size >= sizeof(HALF)) + { + const HALF * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(HALF) + 1); icount += sizeof(HALF)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(XMConvertHalfToFloat(*sPtr++), 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + if (size >= sizeof(uint16_t)) + { + const uint16_t* __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint16_t) + 1); icount += sizeof(uint16_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++) / 65535.f, 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R16_UINT: + if (size >= sizeof(uint16_t)) + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint16_t) + 1); icount += sizeof(uint16_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++), 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R16_SNORM: + if (size >= sizeof(int16_t)) + { + const int16_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(int16_t) + 1); icount += sizeof(int16_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++) / 32767.f, 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R16_SINT: + if (size >= sizeof(int16_t)) + { + const int16_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(int16_t) + 1); icount += sizeof(int16_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++), 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_UNORM: + if (size >= sizeof(uint8_t)) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++) / 255.f, 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_UINT: + if (size >= sizeof(uint8_t)) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++), 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_SNORM: + if (size >= sizeof(int8_t)) + { + const int8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < size; icount += sizeof(int8_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++) / 127.f, 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_SINT: + if (size >= sizeof(int8_t)) + { + const int8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < size; icount += sizeof(int8_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(static_cast(*sPtr++), 0.f, 0.f, 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_A8_UNORM: + if (size >= sizeof(uint8_t)) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(0.f, 0.f, 0.f, static_cast(*sPtr++) / 255.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R1_UNORM: + if (size >= sizeof(uint8_t)) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + for (size_t bcount = 8; bcount > 0; --bcount) + { + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet((((*sPtr >> (bcount - 1)) & 0x1) ? 1.f : 0.f), 0.f, 0.f, 1.f); + } + + ++sPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + LOAD_SCANLINE3(XMFLOAT3SE, XMLoadFloat3SE, g_XMIdentityR3) + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + if (size >= sizeof(XMUBYTEN4)) + { + const XMUBYTEN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + XMVECTOR v = XMLoadUByteN4(sPtr++); + XMVECTOR v1 = XMVectorSwizzle<0, 3, 2, 1>(v); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1110); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v1, g_XMSelect1110); + } + return true; + } + return false; + + case DXGI_FORMAT_G8R8_G8B8_UNORM: + if (size >= sizeof(XMUBYTEN4)) + { + const XMUBYTEN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + XMVECTOR v = XMLoadUByteN4(sPtr++); + XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>(v); + XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>(v); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v0, g_XMSelect1110); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v1, g_XMSelect1110); + } + return true; + } + return false; + + case DXGI_FORMAT_B5G6R5_UNORM: + if (size >= sizeof(XMU565)) + { + static const XMVECTORF32 s_Scale = { { { 1.f / 31.f, 1.f / 63.f, 1.f / 31.f, 1.f } } }; + const XMU565 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMU565) + 1); icount += sizeof(XMU565)) + { + XMVECTOR v = XMLoadU565(sPtr++); + v = XMVectorMultiply(v, s_Scale); + v = XMVectorSwizzle<2, 1, 0, 3>(v); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1110); + } + return true; + } + return false; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + if (size >= sizeof(XMU555)) + { + static const XMVECTORF32 s_Scale = { { { 1.f / 31.f, 1.f / 31.f, 1.f / 31.f, 1.f } } }; + const XMU555 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMU555) + 1); icount += sizeof(XMU555)) + { + XMVECTOR v = XMLoadU555(sPtr++); + v = XMVectorMultiply(v, s_Scale); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>(v); + } + return true; + } + return false; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + if (size >= sizeof(XMUBYTEN4)) + { + const XMUBYTEN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + XMVECTOR v = XMLoadUByteN4(sPtr++); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>(v); + } + return true; + } + return false; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + if (size >= sizeof(XMUBYTEN4)) + { + const XMUBYTEN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + XMVECTOR v = XMLoadUByteN4(sPtr++); + v = XMVectorSwizzle<2, 1, 0, 3>(v); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1110); + } + return true; + } + return false; + + case DXGI_FORMAT_AYUV: + if (size >= sizeof(XMUBYTEN4)) + { + const XMUBYTEN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + int v = int(sPtr->x) - 128; + int u = int(sPtr->y) - 128; + int y = int(sPtr->z) - 16; + unsigned int a = sPtr->w; + ++sPtr; + + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd206750.aspx + + // Y’ = Y - 16 + // Cb’ = Cb - 128 + // Cr’ = Cr - 128 + + // R = 1.1644Y’ + 1.5960Cr’ + // G = 1.1644Y’ - 0.3917Cb’ - 0.8128Cr’ + // B = 1.1644Y’ + 2.0172Cb’ + + int r = (298 * y + 409 * v + 128) >> 8; + int g = (298 * y - 100 * u - 208 * v + 128) >> 8; + int b = (298 * y + 516 * u + 128) >> 8; + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 255)) / 255.f, + float(std::min(std::max(g, 0), 255)) / 255.f, + float(std::min(std::max(b, 0), 255)) / 255.f, + float(a / 255.f)); + } + return true; + } + return false; + + case DXGI_FORMAT_Y410: + if (size >= sizeof(XMUDECN4)) + { + const XMUDECN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUDECN4) + 1); icount += sizeof(XMUDECN4)) + { + int64_t u = int(sPtr->x) - 512; + int64_t y = int(sPtr->y) - 64; + int64_t v = int(sPtr->z) - 512; + unsigned int a = sPtr->w; + ++sPtr; + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx + + // Y’ = Y - 64 + // Cb’ = Cb - 512 + // Cr’ = Cr - 512 + + // R = 1.1678Y’ + 1.6007Cr’ + // G = 1.1678Y’ - 0.3929Cb’ - 0.8152Cr’ + // B = 1.1678Y’ + 2.0232Cb’ + + int r = static_cast((76533 * y + 104905 * v + 32768) >> 16); + int g = static_cast((76533 * y - 25747 * u - 53425 * v + 32768) >> 16); + int b = static_cast((76533 * y + 132590 * u + 32768) >> 16); + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 1023)) / 1023.f, + float(std::min(std::max(g, 0), 1023)) / 1023.f, + float(std::min(std::max(b, 0), 1023)) / 1023.f, + float(a / 3.f)); + } + return true; + } + return false; + + case DXGI_FORMAT_Y416: + if (size >= sizeof(XMUSHORTN4)) + { + const XMUSHORTN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUSHORTN4) + 1); icount += sizeof(XMUSHORTN4)) + { + int64_t u = int64_t(sPtr->x) - 32768; + int64_t y = int64_t(sPtr->y) - 4096; + int64_t v = int64_t(sPtr->z) - 32768; + unsigned int a = sPtr->w; + ++sPtr; + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx + + // Y’ = Y - 4096 + // Cb’ = Cb - 32768 + // Cr’ = Cr - 32768 + + // R = 1.1689Y’ + 1.6023Cr’ + // G = 1.1689Y’ - 0.3933Cb’ - 0.8160Cr’ + // B = 1.1689Y’+ 2.0251Cb’ + + int r = static_cast((76607 * y + 105006 * v + 32768) >> 16); + int g = static_cast((76607 * y - 25772 * u - 53477 * v + 32768) >> 16); + int b = static_cast((76607 * y + 132718 * u + 32768) >> 16); + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 65535)) / 65535.f, + float(std::min(std::max(g, 0), 65535)) / 65535.f, + float(std::min(std::max(b, 0), 65535)) / 65535.f, + float(std::min(std::max(a, 0), 65535)) / 65535.f); + } + return true; + } + return false; + + case DXGI_FORMAT_YUY2: + if (size >= sizeof(XMUBYTEN4)) + { + const XMUBYTEN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + int y0 = int(sPtr->x) - 16; + int u = int(sPtr->y) - 128; + int y1 = int(sPtr->z) - 16; + int v = int(sPtr->w) - 128; + ++sPtr; + + // See AYUV + int r = (298 * y0 + 409 * v + 128) >> 8; + int g = (298 * y0 - 100 * u - 208 * v + 128) >> 8; + int b = (298 * y0 + 516 * u + 128) >> 8; + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 255)) / 255.f, + float(std::min(std::max(g, 0), 255)) / 255.f, + float(std::min(std::max(b, 0), 255)) / 255.f, + 1.f); + + r = (298 * y1 + 409 * v + 128) >> 8; + g = (298 * y1 - 100 * u - 208 * v + 128) >> 8; + b = (298 * y1 + 516 * u + 128) >> 8; + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 255)) / 255.f, + float(std::min(std::max(g, 0), 255)) / 255.f, + float(std::min(std::max(b, 0), 255)) / 255.f, + 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_Y210: + // Same as Y216 with least significant 6 bits set to zero + if (size >= sizeof(XMUSHORTN4)) + { + const XMUSHORTN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUSHORTN4) + 1); icount += sizeof(XMUSHORTN4)) + { + int64_t y0 = int64_t(sPtr->x >> 6) - 64; + int64_t u = int64_t(sPtr->y >> 6) - 512; + int64_t y1 = int64_t(sPtr->z >> 6) - 64; + int64_t v = int64_t(sPtr->w >> 6) - 512; + ++sPtr; + + // See Y410 + int r = static_cast((76533 * y0 + 104905 * v + 32768) >> 16); + int g = static_cast((76533 * y0 - 25747 * u - 53425 * v + 32768) >> 16); + int b = static_cast((76533 * y0 + 132590 * u + 32768) >> 16); + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 1023)) / 1023.f, + float(std::min(std::max(g, 0), 1023)) / 1023.f, + float(std::min(std::max(b, 0), 1023)) / 1023.f, + 1.f); + + r = static_cast((76533 * y1 + 104905 * v + 32768) >> 16); + g = static_cast((76533 * y1 - 25747 * u - 53425 * v + 32768) >> 16); + b = static_cast((76533 * y1 + 132590 * u + 32768) >> 16); + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 1023)) / 1023.f, + float(std::min(std::max(g, 0), 1023)) / 1023.f, + float(std::min(std::max(b, 0), 1023)) / 1023.f, + 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_Y216: + if (size >= sizeof(XMUSHORTN4)) + { + const XMUSHORTN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUSHORTN4) + 1); icount += sizeof(XMUSHORTN4)) + { + int64_t y0 = int64_t(sPtr->x) - 4096; + int64_t u = int64_t(sPtr->y) - 32768; + int64_t y1 = int64_t(sPtr->z) - 4096; + int64_t v = int64_t(sPtr->w) - 32768; + ++sPtr; + + // See Y416 + int r = static_cast((76607 * y0 + 105006 * v + 32768) >> 16); + int g = static_cast((76607 * y0 - 25772 * u - 53477 * v + 32768) >> 16); + int b = static_cast((76607 * y0 + 132718 * u + 32768) >> 16); + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 65535)) / 65535.f, + float(std::min(std::max(g, 0), 65535)) / 65535.f, + float(std::min(std::max(b, 0), 65535)) / 65535.f, + 1.f); + + r = static_cast((76607 * y1 + 105006 * v + 32768) >> 16); + g = static_cast((76607 * y1 - 25772 * u - 53477 * v + 32768) >> 16); + b = static_cast((76607 * y1 + 132718 * u + 32768) >> 16); + + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSet(float(std::min(std::max(r, 0), 65535)) / 65535.f, + float(std::min(std::max(g, 0), 65535)) / 65535.f, + float(std::min(std::max(b, 0), 65535)) / 65535.f, + 1.f); + } + return true; + } + return false; + + case DXGI_FORMAT_B4G4R4A4_UNORM: + if (size >= sizeof(XMUNIBBLE4)) + { + static const XMVECTORF32 s_Scale = { { { 1.f / 15.f, 1.f / 15.f, 1.f / 15.f, 1.f / 15.f } } }; + const XMUNIBBLE4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUNIBBLE4) + 1); icount += sizeof(XMUNIBBLE4)) + { + XMVECTOR v = XMLoadUNibble4(sPtr++); + v = XMVectorMultiply(v, s_Scale); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>(v); + } + return true; + } + return false; + + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + // Xbox One specific 7e3 format + if (size >= sizeof(XMUDECN4)) + { + const XMUDECN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUDECN4) + 1); icount += sizeof(XMUDECN4)) + { + if (dPtr >= ePtr) break; + + XMVECTORF32 vResult = { { { + FloatFrom7e3(sPtr->x), + FloatFrom7e3(sPtr->y), + FloatFrom7e3(sPtr->z), + (float)(sPtr->v >> 30) / 3.0f + } } }; + + ++sPtr; + + *(dPtr++) = vResult.v; + } + return true; + } + return false; + + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + // Xbox One specific 6e4 format + if (size >= sizeof(XMUDECN4)) + { + const XMUDECN4 * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(XMUDECN4) + 1); icount += sizeof(XMUDECN4)) + { + if (dPtr >= ePtr) break; + + XMVECTORF32 vResult = { { { + FloatFrom6e4(sPtr->x), + FloatFrom6e4(sPtr->y), + FloatFrom6e4(sPtr->z), + (float)(sPtr->v >> 30) / 3.0f + } } }; + + ++sPtr; + + *(dPtr++) = vResult.v; + } + return true; + } + return false; + + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + // Xbox One specific format + LOAD_SCANLINE(XMXDECN4, XMLoadXDecN4); + + case XBOX_DXGI_FORMAT_R4G4_UNORM: + // Xbox One specific format + if (size >= sizeof(uint8_t)) + { + static const XMVECTORF32 s_Scale = { { { 1.f / 15.f, 1.f / 15.f, 0.f, 0.f } } }; + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + for (size_t icount = 0; icount < (size - sizeof(uint8_t) + 1); icount += sizeof(uint8_t)) + { + XMUNIBBLE4 nibble; + nibble.v = static_cast(*sPtr++); + XMVECTOR v = XMLoadUNibble4(&nibble); + v = XMVectorMultiply(v, s_Scale); + if (dPtr >= ePtr) break; + *(dPtr++) = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1100); + } + return true; + } + return false; + + // We don't support the planar or palettized formats + + default: + return false; + } +} + +#undef LOAD_SCANLINE +#undef LOAD_SCANLINE3 +#undef LOAD_SCANLINE2 + + +//------------------------------------------------------------------------------------- +// Stores an image row from standard RGBA XMVECTOR (aligned) array +//------------------------------------------------------------------------------------- +#define STORE_SCANLINE( type, func )\ + if ( size >= sizeof(type) )\ + {\ + type * __restrict dPtr = reinterpret_cast(pDestination);\ + for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\ + {\ + if ( sPtr >= ePtr ) break;\ + func( dPtr++, *sPtr++ );\ + }\ + return true; \ + }\ + return false; + +_Use_decl_annotations_ +bool DirectX::_StoreScanline( + void* pDestination, + size_t size, + DXGI_FORMAT format, + const XMVECTOR* pSource, + size_t count, + float threshold) +{ + assert(pDestination && size > 0); + assert(pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0)); + assert(IsValid(format) && !IsTypeless(format) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format)); + + const XMVECTOR* __restrict sPtr = pSource; + if (!sPtr) + return false; + + const XMVECTOR* ePtr = pSource + count; + + switch (static_cast(format)) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + STORE_SCANLINE(XMFLOAT4, XMStoreFloat4) + + case DXGI_FORMAT_R32G32B32A32_UINT: + STORE_SCANLINE(XMUINT4, XMStoreUInt4) + + case DXGI_FORMAT_R32G32B32A32_SINT: + STORE_SCANLINE(XMINT4, XMStoreSInt4) + + case DXGI_FORMAT_R32G32B32_FLOAT: + STORE_SCANLINE(XMFLOAT3, XMStoreFloat3) + + case DXGI_FORMAT_R32G32B32_UINT: + STORE_SCANLINE(XMUINT3, XMStoreUInt3) + + case DXGI_FORMAT_R32G32B32_SINT: + STORE_SCANLINE(XMINT3, XMStoreSInt3) + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + if (size >= sizeof(XMHALF4)) + { + XMHALF4* __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMHALF4) + 1); icount += sizeof(XMHALF4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = *sPtr++; + v = XMVectorClamp(v, g_HalfMin, g_HalfMax); + XMStoreHalf4(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_R16G16B16A16_UNORM: + STORE_SCANLINE(XMUSHORTN4, XMStoreUShortN4) + + case DXGI_FORMAT_R16G16B16A16_UINT: + STORE_SCANLINE(XMUSHORT4, XMStoreUShort4) + + case DXGI_FORMAT_R16G16B16A16_SNORM: + STORE_SCANLINE(XMSHORTN4, XMStoreShortN4) + + case DXGI_FORMAT_R16G16B16A16_SINT: + STORE_SCANLINE(XMSHORT4, XMStoreShort4) + + case DXGI_FORMAT_R32G32_FLOAT: + STORE_SCANLINE(XMFLOAT2, XMStoreFloat2) + + case DXGI_FORMAT_R32G32_UINT: + STORE_SCANLINE(XMUINT2, XMStoreUInt2) + + case DXGI_FORMAT_R32G32_SINT: + STORE_SCANLINE(XMINT2, XMStoreSInt2) + + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + const size_t psize = sizeof(float) + sizeof(uint32_t); + if (size >= psize) + { + float *dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - psize + 1); icount += psize) + { + if (sPtr >= ePtr) break; + XMFLOAT4 f; + XMStoreFloat4(&f, *sPtr++); + dPtr[0] = f.x; + uint8_t* ps8 = reinterpret_cast(&dPtr[1]); + ps8[0] = static_cast(std::min(255.f, std::max(0.f, f.y))); + ps8[1] = ps8[2] = ps8[3] = 0; + dPtr += 2; + } + return true; + } + } + return false; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + STORE_SCANLINE(XMUDECN4, XMStoreUDecN4); + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + STORE_SCANLINE(XMUDECN4, XMStoreUDecN4_XR); + + case DXGI_FORMAT_R10G10B10A2_UINT: + STORE_SCANLINE(XMUDEC4, XMStoreUDec4); + + case DXGI_FORMAT_R11G11B10_FLOAT: + STORE_SCANLINE(XMFLOAT3PK, XMStoreFloat3PK); + + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorAdd(*sPtr++, g_8BitBias); + XMStoreUByteN4(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_R8G8B8A8_UINT: + STORE_SCANLINE(XMUBYTE4, XMStoreUByte4) + + case DXGI_FORMAT_R8G8B8A8_SNORM: + STORE_SCANLINE(XMBYTEN4, XMStoreByteN4) + + case DXGI_FORMAT_R8G8B8A8_SINT: + STORE_SCANLINE(XMBYTE4, XMStoreByte4) + + case DXGI_FORMAT_R16G16_FLOAT: + if (size >= sizeof(XMHALF2)) + { + XMHALF2* __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMHALF2) + 1); icount += sizeof(XMHALF2)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = *sPtr++; + v = XMVectorClamp(v, g_HalfMin, g_HalfMax); + XMStoreHalf2(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_R16G16_UNORM: + STORE_SCANLINE(XMUSHORTN2, XMStoreUShortN2) + + case DXGI_FORMAT_R16G16_UINT: + STORE_SCANLINE(XMUSHORT2, XMStoreUShort2) + + case DXGI_FORMAT_R16G16_SNORM: + STORE_SCANLINE(XMSHORTN2, XMStoreShortN2) + + case DXGI_FORMAT_R16G16_SINT: + STORE_SCANLINE(XMSHORT2, XMStoreShort2) + + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + if (size >= sizeof(float)) + { + float * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(float) + 1); icount += sizeof(float)) + { + if (sPtr >= ePtr) break; + XMStoreFloat(dPtr++, *(sPtr++)); + } + return true; + } + return false; + + case DXGI_FORMAT_R32_UINT: + if (size >= sizeof(uint32_t)) + { + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(uint32_t) + 1); icount += sizeof(uint32_t)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMConvertVectorFloatToUInt(*(sPtr++), 0); + XMStoreInt(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_R32_SINT: + if (size >= sizeof(int32_t)) + { + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(int32_t) + 1); icount += sizeof(int32_t)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMConvertVectorFloatToInt(*(sPtr++), 0); + XMStoreInt(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + if (size >= sizeof(uint32_t)) + { + static const XMVECTORF32 clamp = { { { 1.f, 255.f, 0.f, 0.f } } }; + XMVECTOR zero = XMVectorZero(); + uint32_t *dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(uint32_t) + 1); icount += sizeof(uint32_t)) + { + if (sPtr >= ePtr) break; + XMFLOAT4 f; + XMStoreFloat4(&f, XMVectorClamp(*sPtr++, zero, clamp)); + *dPtr++ = (static_cast(f.x * 16777215.f) & 0xFFFFFF) + | ((static_cast(f.y) & 0xFF) << 24); + } + return true; + } + return false; + + case DXGI_FORMAT_R8G8_UNORM: + STORE_SCANLINE(XMUBYTEN2, XMStoreUByteN2) + + case DXGI_FORMAT_R8G8_UINT: + STORE_SCANLINE(XMUBYTE2, XMStoreUByte2) + + case DXGI_FORMAT_R8G8_SNORM: + STORE_SCANLINE(XMBYTEN2, XMStoreByteN2) + + case DXGI_FORMAT_R8G8_SINT: + STORE_SCANLINE(XMBYTE2, XMStoreByte2) + + case DXGI_FORMAT_R16_FLOAT: + if (size >= sizeof(HALF)) + { + HALF * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(HALF) + 1); icount += sizeof(HALF)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 65504.f), -65504.f); + *(dPtr++) = XMConvertFloatToHalf(v); + } + return true; + } + return false; + + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + if (size >= sizeof(uint16_t)) + { + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(uint16_t) + 1); icount += sizeof(uint16_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 1.f), 0.f); + *(dPtr++) = static_cast(v*65535.f + 0.5f); + } + return true; + } + return false; + + case DXGI_FORMAT_R16_UINT: + if (size >= sizeof(uint16_t)) + { + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(uint16_t) + 1); icount += sizeof(uint16_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 65535.f), 0.f); + *(dPtr++) = static_cast(v); + } + return true; + } + return false; + + case DXGI_FORMAT_R16_SNORM: + if (size >= sizeof(int16_t)) + { + int16_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(int16_t) + 1); icount += sizeof(int16_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 1.f), -1.f); + *(dPtr++) = static_cast(v * 32767.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R16_SINT: + if (size >= sizeof(int16_t)) + { + int16_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(int16_t) + 1); icount += sizeof(int16_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 32767.f), -32767.f); + *(dPtr++) = static_cast(v); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_UNORM: + if (size >= sizeof(uint8_t)) + { + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 1.f), 0.f); + *(dPtr++) = static_cast(v * 255.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_UINT: + if (size >= sizeof(uint8_t)) + { + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 255.f), 0.f); + *(dPtr++) = static_cast(v); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_SNORM: + if (size >= sizeof(int8_t)) + { + int8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < size; icount += sizeof(int8_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 1.f), -1.f); + *(dPtr++) = static_cast(v * 127.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R8_SINT: + if (size >= sizeof(int8_t)) + { + int8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < size; icount += sizeof(int8_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + v = std::max(std::min(v, 127.f), -127.f); + *(dPtr++) = static_cast(v); + } + return true; + } + return false; + + case DXGI_FORMAT_A8_UNORM: + if (size >= sizeof(uint8_t)) + { + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetW(*sPtr++); + v = std::max(std::min(v, 1.f), 0.f); + *(dPtr++) = static_cast(v * 255.f); + } + return true; + } + return false; + + case DXGI_FORMAT_R1_UNORM: + if (size >= sizeof(uint8_t)) + { + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < size; icount += sizeof(uint8_t)) + { + uint8_t pixels = 0; + for (size_t bcount = 8; bcount > 0; --bcount) + { + if (sPtr >= ePtr) break; + float v = XMVectorGetX(*sPtr++); + + // Absolute thresholding generally doesn't give good results for all images + // Picking the 'right' threshold automatically requires whole-image analysis + + if (v > 0.25f) + pixels |= 1 << (bcount - 1); + } + *(dPtr++) = pixels; + } + return true; + } + return false; + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + STORE_SCANLINE(XMFLOAT3SE, StoreFloat3SE) + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v0 = *sPtr++; + XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY(*sPtr++) : XMVectorZero(); + XMVECTOR v = XMVectorSelect(v1, v0, g_XMSelect1110); + v = XMVectorAdd(v, g_8BitBias); + XMStoreUByteN4(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_G8R8_G8B8_UNORM: + if (size >= sizeof(XMUBYTEN4)) + { + static XMVECTORU32 select1101 = { { { XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1 } } }; + + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>(*sPtr++); + XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY(*sPtr++) : XMVectorZero(); + XMVECTOR v = XMVectorSelect(v1, v0, select1101); + v = XMVectorAdd(v, g_8BitBias); + XMStoreUByteN4(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_B5G6R5_UNORM: + if (size >= sizeof(XMU565)) + { + static const XMVECTORF32 s_Scale = { { { 31.f, 63.f, 31.f, 1.f } } }; + XMU565 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMU565) + 1); icount += sizeof(XMU565)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(*sPtr++); + v = XMVectorMultiply(v, s_Scale); + XMStoreU565(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + if (size >= sizeof(XMU555)) + { + static const XMVECTORF32 s_Scale = { { { 31.f, 31.f, 31.f, 1.f } } }; + XMU555 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMU555) + 1); icount += sizeof(XMU555)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(*sPtr++); + v = XMVectorMultiply(v, s_Scale); + XMStoreU555(dPtr, v); + dPtr->w = (XMVectorGetW(v) > threshold) ? 1 : 0; + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(*sPtr++); + v = XMVectorAdd(v, g_8BitBias); + XMStoreUByteN4(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorPermute<2, 1, 0, 7>(*sPtr++, g_XMIdentityR3); + v = XMVectorAdd(v, g_8BitBias); + XMStoreUByteN4(dPtr++, v); + } + return true; + } + return false; + + case DXGI_FORMAT_AYUV: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + + XMUBYTEN4 rgba; + XMStoreUByteN4(&rgba, *sPtr++); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd206750.aspx + + // Y = 0.2568R + 0.5041G + 0.1001B + 16 + // Cb = -0.1482R - 0.2910G + 0.4392B + 128 + // Cr = 0.4392R - 0.3678G - 0.0714B + 128 + + int y = ((66 * rgba.x + 129 * rgba.y + 25 * rgba.z + 128) >> 8) + 16; + int u = ((-38 * rgba.x - 74 * rgba.y + 112 * rgba.z + 128) >> 8) + 128; + int v = ((112 * rgba.x - 94 * rgba.y - 18 * rgba.z + 128) >> 8) + 128; + + dPtr->x = static_cast(std::min(std::max(v, 0), 255)); + dPtr->y = static_cast(std::min(std::max(u, 0), 255)); + dPtr->z = static_cast(std::min(std::max(y, 0), 255)); + dPtr->w = rgba.w; + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_Y410: + if (size >= sizeof(XMUDECN4)) + { + XMUDECN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUDECN4) + 1); icount += sizeof(XMUDECN4)) + { + if (sPtr >= ePtr) break; + + XMUDECN4 rgba; + XMStoreUDecN4(&rgba, *sPtr++); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx + + // Y = 0.2560R + 0.5027G + 0.0998B + 64 + // Cb = -0.1478R - 0.2902G + 0.4379B + 512 + // Cr = 0.4379R - 0.3667G - 0.0712B + 512 + + int64_t r = rgba.x; + int64_t g = rgba.y; + int64_t b = rgba.z; + + int y = static_cast((16780 * r + 32942 * g + 6544 * b + 32768) >> 16) + 64; + int u = static_cast((-9683 * r - 19017 * g + 28700 * b + 32768) >> 16) + 512; + int v = static_cast((28700 * r - 24033 * g - 4667 * b + 32768) >> 16) + 512; + + dPtr->x = static_cast(std::min(std::max(u, 0), 1023)); + dPtr->y = static_cast(std::min(std::max(y, 0), 1023)); + dPtr->z = static_cast(std::min(std::max(v, 0), 1023)); + dPtr->w = rgba.w; + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_Y416: + if (size >= sizeof(XMUSHORTN4)) + { + XMUSHORTN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUSHORTN4) + 1); icount += sizeof(XMUSHORTN4)) + { + if (sPtr >= ePtr) break; + + XMUSHORTN4 rgba; + XMStoreUShortN4(&rgba, *sPtr++); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx + + // Y = 0.2558R + 0.5022G + 0.0998B + 4096 + // Cb = -0.1476R - 0.2899G + 0.4375B + 32768 + // Cr = 0.4375R - 0.3664G - 0.0711B + 32768 + + int64_t r = int64_t(rgba.x); + int64_t g = int64_t(rgba.y); + int64_t b = int64_t(rgba.z); + + int y = static_cast((16763 * r + 32910 * g + 6537 * b + 32768) >> 16) + 4096; + int u = static_cast((-9674 * r - 18998 * g + 28672 * b + 32768) >> 16) + 32768; + int v = static_cast((28672 * r - 24010 * g - 4662 * b + 32768) >> 16) + 32768; + + dPtr->x = static_cast(std::min(std::max(u, 0), 65535)); + dPtr->y = static_cast(std::min(std::max(y, 0), 65535)); + dPtr->z = static_cast(std::min(std::max(v, 0), 65535)); + dPtr->w = rgba.w; + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_YUY2: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUBYTEN4) + 1); icount += sizeof(XMUBYTEN4)) + { + if (sPtr >= ePtr) break; + + XMUBYTEN4 rgb1; + XMStoreUByteN4(&rgb1, *sPtr++); + + // See AYUV + int y0 = ((66 * rgb1.x + 129 * rgb1.y + 25 * rgb1.z + 128) >> 8) + 16; + int u0 = ((-38 * rgb1.x - 74 * rgb1.y + 112 * rgb1.z + 128) >> 8) + 128; + int v0 = ((112 * rgb1.x - 94 * rgb1.y - 18 * rgb1.z + 128) >> 8) + 128; + + XMUBYTEN4 rgb2; + if (sPtr < ePtr) + { + XMStoreUByteN4(&rgb2, *sPtr++); + } + else + { + rgb2.x = rgb2.y = rgb2.z = rgb2.w = 0; + } + + int y1 = ((66 * rgb2.x + 129 * rgb2.y + 25 * rgb2.z + 128) >> 8) + 16; + int u1 = ((-38 * rgb2.x - 74 * rgb2.y + 112 * rgb2.z + 128) >> 8) + 128; + int v1 = ((112 * rgb2.x - 94 * rgb2.y - 18 * rgb2.z + 128) >> 8) + 128; + + dPtr->x = static_cast(std::min(std::max(y0, 0), 255)); + dPtr->y = static_cast(std::min(std::max((u0 + u1) >> 1, 0), 255)); + dPtr->z = static_cast(std::min(std::max(y1, 0), 255)); + dPtr->w = static_cast(std::min(std::max((v0 + v1) >> 1, 0), 255)); + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_Y210: + // Same as Y216 with least significant 6 bits set to zero + if (size >= sizeof(XMUSHORTN4)) + { + XMUSHORTN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUSHORTN4) + 1); icount += sizeof(XMUSHORTN4)) + { + if (sPtr >= ePtr) break; + + XMUDECN4 rgb1; + XMStoreUDecN4(&rgb1, *sPtr++); + + // See Y410 + int64_t r = rgb1.x; + int64_t g = rgb1.y; + int64_t b = rgb1.z; + + int y0 = static_cast((16780 * r + 32942 * g + 6544 * b + 32768) >> 16) + 64; + int u0 = static_cast((-9683 * r - 19017 * g + 28700 * b + 32768) >> 16) + 512; + int v0 = static_cast((28700 * r - 24033 * g - 4667 * b + 32768) >> 16) + 512; + + XMUDECN4 rgb2; + if (sPtr < ePtr) + { + XMStoreUDecN4(&rgb2, *sPtr++); + } + else + { + rgb2.x = rgb2.y = rgb2.z = rgb2.w = 0; + } + + r = rgb2.x; + g = rgb2.y; + b = rgb2.z; + + int y1 = static_cast((16780 * r + 32942 * g + 6544 * b + 32768) >> 16) + 64; + int u1 = static_cast((-9683 * r - 19017 * g + 28700 * b + 32768) >> 16) + 512; + int v1 = static_cast((28700 * r - 24033 * g - 4667 * b + 32768) >> 16) + 512; + + dPtr->x = static_cast(std::min(std::max(y0, 0), 1023) << 6); + dPtr->y = static_cast(std::min(std::max((u0 + u1) >> 1, 0), 1023) << 6); + dPtr->z = static_cast(std::min(std::max(y1, 0), 1023) << 6); + dPtr->w = static_cast(std::min(std::max((v0 + v1) >> 1, 0), 1023) << 6); + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_Y216: + if (size >= sizeof(XMUSHORTN4)) + { + XMUSHORTN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUSHORTN4) + 1); icount += sizeof(XMUSHORTN4)) + { + if (sPtr >= ePtr) break; + + XMUSHORTN4 rgb1; + XMStoreUShortN4(&rgb1, *sPtr++); + + // See Y416 + int64_t r = int64_t(rgb1.x); + int64_t g = int64_t(rgb1.y); + int64_t b = int64_t(rgb1.z); + + int y0 = static_cast((16763 * r + 32910 * g + 6537 * b + 32768) >> 16) + 4096; + int u0 = static_cast((-9674 * r - 18998 * g + 28672 * b + 32768) >> 16) + 32768; + int v0 = static_cast((28672 * r - 24010 * g - 4662 * b + 32768) >> 16) + 32768; + + XMUSHORTN4 rgb2; + if (sPtr < ePtr) + { + XMStoreUShortN4(&rgb2, *sPtr++); + } + else + { + rgb2.x = rgb2.y = rgb2.z = rgb2.w = 0; + } + + r = int64_t(rgb2.x); + g = int64_t(rgb2.y); + b = int64_t(rgb2.z); + + int y1 = static_cast((16763 * r + 32910 * g + 6537 * b + 32768) >> 16) + 4096; + int u1 = static_cast((-9674 * r - 18998 * g + 28672 * b + 32768) >> 16) + 32768; + int v1 = static_cast((28672 * r - 24010 * g - 4662 * b + 32768) >> 16) + 32768; + + dPtr->x = static_cast(std::min(std::max(y0, 0), 65535)); + dPtr->y = static_cast(std::min(std::max((u0 + u1) >> 1, 0), 65535)); + dPtr->z = static_cast(std::min(std::max(y1, 0), 65535)); + dPtr->w = static_cast(std::min(std::max((v0 + v1) >> 1, 0), 65535)); + ++dPtr; + } + return true; + } + return false; + + case DXGI_FORMAT_B4G4R4A4_UNORM: + if (size >= sizeof(XMUNIBBLE4)) + { + static const XMVECTORF32 s_Scale = { { { 15.f, 15.f, 15.f, 15.f } } }; + XMUNIBBLE4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUNIBBLE4) + 1); icount += sizeof(XMUNIBBLE4)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(*sPtr++); + v = XMVectorMultiply(v, s_Scale); + XMStoreUNibble4(dPtr++, v); + } + return true; + } + return false; + + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + // Xbox One specific 7e3 format with alpha + if (size >= sizeof(XMUDECN4)) + { + static const XMVECTORF32 Scale = { { { 1.0f, 1.0f, 1.0f, 3.0f } } }; + static const XMVECTORF32 C = { { { 31.875f, 31.875f, 31.875f, 3.f } } }; + + XMUDECN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUDECN4) + 1); icount += sizeof(XMUDECN4)) + { + if (sPtr >= ePtr) break; + + XMVECTOR V = XMVectorMultiply(*sPtr++, Scale); + V = XMVectorClamp(V, g_XMZero, C); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, V); + + dPtr->x = FloatTo7e3(tmp.x); + dPtr->y = FloatTo7e3(tmp.y); + dPtr->z = FloatTo7e3(tmp.z); + dPtr->w = (uint32_t)tmp.w; + ++dPtr; + } + return true; + } + return false; + + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + // Xbox One specific 6e4 format with alpha + if (size >= sizeof(XMUDECN4)) + { + static const XMVECTORF32 Scale = { { { 1.0f, 1.0f, 1.0f, 3.0f } } }; + static const XMVECTORF32 C = { { { 508.f, 508.f, 508.f, 3.f } } }; + + XMUDECN4 * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(XMUDECN4) + 1); icount += sizeof(XMUDECN4)) + { + if (sPtr >= ePtr) break; + + XMVECTOR V = XMVectorMultiply(*sPtr++, Scale); + V = XMVectorClamp(V, g_XMZero, C); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, V); + + dPtr->x = FloatTo6e4(tmp.x); + dPtr->y = FloatTo6e4(tmp.y); + dPtr->z = FloatTo6e4(tmp.z); + dPtr->w = (uint32_t)tmp.w; + ++dPtr; + } + return true; + } + return false; + + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + // Xbox One specific format + STORE_SCANLINE(XMXDECN4, XMStoreXDecN4); + + case XBOX_DXGI_FORMAT_R4G4_UNORM: + // Xbox One specific format + if (size >= sizeof(uint8_t)) + { + static const XMVECTORF32 s_Scale = { { { 15.f, 15.f, 0.f, 0.f } } }; + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + for (size_t icount = 0; icount < (size - sizeof(uint8_t) + 1); icount += sizeof(uint8_t)) + { + if (sPtr >= ePtr) break; + XMVECTOR v = XMVectorMultiply(*sPtr++, s_Scale); + + XMUNIBBLE4 nibble; + XMStoreUNibble4(&nibble, v); + *dPtr = static_cast(nibble.v); + ++dPtr; + } + return true; + } + return false; + + // We don't support the planar or palettized formats + + default: + return false; + } +} + +#undef STORE_SCANLINE + + +//------------------------------------------------------------------------------------- +// Convert DXGI image to/from GUID_WICPixelFormat128bppRGBAFloat (no range conversions) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::_ConvertToR32G32B32A32(const Image& srcImage, ScratchImage& image) +{ + if (!srcImage.pixels) + return E_POINTER; + + HRESULT hr = image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + uint8_t* pDest = img->pixels; + if (!pDest) + { + image.Release(); + return E_POINTER; + } + + const uint8_t *pSrc = srcImage.pixels; + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(reinterpret_cast(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format)) + { + image.Release(); + return E_FAIL; + } + + pSrc += srcImage.rowPitch; + pDest += img->rowPitch; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::_ConvertFromR32G32B32A32(const Image& srcImage, const Image& destImage) +{ + assert(srcImage.format == DXGI_FORMAT_R32G32B32A32_FLOAT); + + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + if (srcImage.width != destImage.width || srcImage.height != destImage.height) + return E_FAIL; + + const uint8_t *pSrc = srcImage.pixels; + uint8_t* pDest = destImage.pixels; + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, reinterpret_cast(pSrc), srcImage.width)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::_ConvertFromR32G32B32A32(const Image& srcImage, DXGI_FORMAT format, ScratchImage& image) +{ + if (!srcImage.pixels) + return E_POINTER; + + HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + hr = _ConvertFromR32G32B32A32(srcImage, *img); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::_ConvertFromR32G32B32A32( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DXGI_FORMAT format, + ScratchImage& result) +{ + if (!srcImages) + return E_POINTER; + + result.Release(); + + assert(metadata.format == DXGI_FORMAT_R32G32B32A32_FLOAT); + + TexMetadata mdata2 = metadata; + mdata2.format = format; + HRESULT hr = result.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) + { + result.Release(); + return E_FAIL; + } + + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } + + for (size_t index = 0; index < nimages; ++index) + { + const Image& src = srcImages[index]; + const Image& dst = dest[index]; + + assert(src.format == DXGI_FORMAT_R32G32B32A32_FLOAT); + assert(dst.format == format); + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + const uint8_t* pSrc = src.pixels; + uint8_t* pDest = dst.pixels; + if (!pSrc || !pDest) + { + result.Release(); + return E_POINTER; + } + + for (size_t h = 0; h < src.height; ++h) + { + if (!_StoreScanline(pDest, dst.rowPitch, format, reinterpret_cast(pSrc), src.width)) + { + result.Release(); + return E_FAIL; + } + + pSrc += src.rowPitch; + pDest += dst.rowPitch; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Convert from Linear RGB to sRGB +// +// if C_linear <= 0.0031308 -> C_srgb = 12.92 * C_linear +// if C_linear > 0.0031308 -> C_srgb = ( 1 + a ) * pow( C_Linear, 1 / 2.4 ) - a +// where a = 0.055 +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::_StoreScanlineLinear( + void* pDestination, + size_t size, + DXGI_FORMAT format, + XMVECTOR* pSource, + size_t count, + DWORD flags, + float threshold) +{ + assert(pDestination && size > 0); + assert(pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0)); + assert(IsValid(format) && !IsTypeless(format) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format)); + + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + flags |= TEX_FILTER_SRGB; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + break; + + default: + // can't treat A8, XR, Depth, SNORM, UINT, or SINT as sRGB + flags &= ~TEX_FILTER_SRGB; + break; + } + + // sRGB output processing (Linear RGB -> sRGB) + if (flags & TEX_FILTER_SRGB_OUT) + { + // To avoid the need for another temporary scanline buffer, we allow this function to overwrite the source buffer in-place + // Given the intended usage in the filtering routines, this is not a problem. + XMVECTOR* ptr = pSource; + for (size_t i = 0; i < count; ++i, ++ptr) + { + *ptr = XMColorRGBToSRGB(*ptr); + } + } + + return _StoreScanline(pDestination, size, format, pSource, count, threshold); +} + + +//------------------------------------------------------------------------------------- +// Convert from sRGB to Linear RGB +// +// if C_srgb <= 0.04045 -> C_linear = C_srgb / 12.92 +// if C_srgb > 0.04045 -> C_linear = pow( ( C_srgb + a ) / ( 1 + a ), 2.4 ) +// where a = 0.055 +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::_LoadScanlineLinear( + XMVECTOR* pDestination, + size_t count, + const void* pSource, + size_t size, + DXGI_FORMAT format, + DWORD flags) +{ + assert(pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0)); + assert(pSource && size > 0); + assert(IsValid(format) && !IsTypeless(format, false) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format)); + + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + flags |= TEX_FILTER_SRGB; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + break; + + default: + // can't treat A8, XR, Depth, SNORM, UINT, or SINT as sRGB + flags &= ~TEX_FILTER_SRGB; + break; + } + + if (_LoadScanline(pDestination, count, pSource, size, format)) + { + // sRGB input processing (sRGB -> Linear RGB) + if (flags & TEX_FILTER_SRGB_IN) + { + XMVECTOR* ptr = pDestination; + for (size_t i = 0; i < count; ++i, ++ptr) + { + *ptr = XMColorSRGBToRGB(*ptr); + } + } + + return true; + } + + return false; +} + + +//------------------------------------------------------------------------------------- +// Convert scanline based on source/target formats +//------------------------------------------------------------------------------------- +namespace +{ + struct ConvertData + { + DXGI_FORMAT format; + size_t datasize; + DWORD flags; + }; + + const ConvertData g_ConvertTable[] = + { + { DXGI_FORMAT_R32G32B32A32_FLOAT, 32, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R32G32B32A32_UINT, 32, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R32G32B32A32_SINT, 32, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R32G32B32_FLOAT, 32, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_R32G32B32_UINT, 32, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_R32G32B32_SINT, 32, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_R16G16B16A16_FLOAT, 16, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R16G16B16A16_UNORM, 16, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R16G16B16A16_UINT, 16, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R16G16B16A16_SNORM, 16, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R16G16B16A16_SINT, 16, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R32G32_FLOAT, 32, CONVF_FLOAT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R32G32_UINT, 32, CONVF_UINT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R32G32_SINT, 32, CONVF_SINT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, CONVF_FLOAT | CONVF_DEPTH | CONVF_STENCIL }, + { DXGI_FORMAT_R10G10B10A2_UNORM, 10, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R10G10B10A2_UINT, 10, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R11G11B10_FLOAT, 10, CONVF_FLOAT | CONVF_POS_ONLY | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_R8G8B8A8_UNORM, 8, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R8G8B8A8_UINT, 8, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R8G8B8A8_SNORM, 8, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R8G8B8A8_SINT, 8, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_R16G16_FLOAT, 16, CONVF_FLOAT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R16G16_UNORM, 16, CONVF_UNORM | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R16G16_UINT, 16, CONVF_UINT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R16G16_SNORM, 16, CONVF_SNORM | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R16G16_SINT, 16, CONVF_SINT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_D32_FLOAT, 32, CONVF_FLOAT | CONVF_DEPTH }, + { DXGI_FORMAT_R32_FLOAT, 32, CONVF_FLOAT | CONVF_R }, + { DXGI_FORMAT_R32_UINT, 32, CONVF_UINT | CONVF_R }, + { DXGI_FORMAT_R32_SINT, 32, CONVF_SINT | CONVF_R }, + { DXGI_FORMAT_D24_UNORM_S8_UINT, 32, CONVF_UNORM | CONVF_DEPTH | CONVF_STENCIL }, + { DXGI_FORMAT_R8G8_UNORM, 8, CONVF_UNORM | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R8G8_UINT, 8, CONVF_UINT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R8G8_SNORM, 8, CONVF_SNORM | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R8G8_SINT, 8, CONVF_SINT | CONVF_R | CONVF_G }, + { DXGI_FORMAT_R16_FLOAT, 16, CONVF_FLOAT | CONVF_R }, + { DXGI_FORMAT_D16_UNORM, 16, CONVF_UNORM | CONVF_DEPTH }, + { DXGI_FORMAT_R16_UNORM, 16, CONVF_UNORM | CONVF_R }, + { DXGI_FORMAT_R16_UINT, 16, CONVF_UINT | CONVF_R }, + { DXGI_FORMAT_R16_SNORM, 16, CONVF_SNORM | CONVF_R }, + { DXGI_FORMAT_R16_SINT, 16, CONVF_SINT | CONVF_R }, + { DXGI_FORMAT_R8_UNORM, 8, CONVF_UNORM | CONVF_R }, + { DXGI_FORMAT_R8_UINT, 8, CONVF_UINT | CONVF_R }, + { DXGI_FORMAT_R8_SNORM, 8, CONVF_SNORM | CONVF_R }, + { DXGI_FORMAT_R8_SINT, 8, CONVF_SINT | CONVF_R }, + { DXGI_FORMAT_A8_UNORM, 8, CONVF_UNORM | CONVF_A }, + { DXGI_FORMAT_R1_UNORM, 1, CONVF_UNORM | CONVF_R }, + { DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, CONVF_FLOAT | CONVF_SHAREDEXP | CONVF_POS_ONLY | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_R8G8_B8G8_UNORM, 8, CONVF_UNORM | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_G8R8_G8B8_UNORM, 8, CONVF_UNORM | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_BC1_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC1_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC2_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC2_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC3_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC3_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC4_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R }, + { DXGI_FORMAT_BC4_SNORM, 8, CONVF_SNORM | CONVF_BC | CONVF_R }, + { DXGI_FORMAT_BC5_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G }, + { DXGI_FORMAT_BC5_SNORM, 8, CONVF_SNORM | CONVF_BC | CONVF_R | CONVF_G }, + { DXGI_FORMAT_B5G6R5_UNORM, 5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_B5G5R5A1_UNORM, 5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_B8G8R8A8_UNORM, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_B8G8R8X8_UNORM, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, 10, CONVF_UNORM | CONVF_XR | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_BC6H_UF16, 16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC6H_SF16, 16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC7_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_BC7_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_AYUV, 8, CONVF_UNORM | CONVF_YUV | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_Y410, 10, CONVF_UNORM | CONVF_YUV | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_Y416, 16, CONVF_UNORM | CONVF_YUV | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { DXGI_FORMAT_YUY2, 8, CONVF_UNORM | CONVF_YUV | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_Y210, 10, CONVF_UNORM | CONVF_YUV | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_Y216, 16, CONVF_UNORM | CONVF_YUV | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B }, + { DXGI_FORMAT_B4G4R4A4_UNORM, 4, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT, 10, CONVF_FLOAT | CONVF_POS_ONLY | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT, 10, CONVF_FLOAT | CONVF_POS_ONLY | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM,10, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, + { XBOX_DXGI_FORMAT_R4G4_UNORM, 4, CONVF_UNORM | CONVF_R | CONVF_G }, + }; + +#pragma prefast( suppress : 25004, "Signature must match bsearch_s" ); + int __cdecl _ConvertCompare(void *context, const void* ptr1, const void *ptr2) + { + UNREFERENCED_PARAMETER(context); + const ConvertData *p1 = reinterpret_cast(ptr1); + const ConvertData *p2 = reinterpret_cast(ptr2); + if (p1->format == p2->format) return 0; + else return (p1->format < p2->format) ? -1 : 1; + } +} + +_Use_decl_annotations_ +DWORD DirectX::_GetConvertFlags(DXGI_FORMAT format) +{ +#ifdef _DEBUG + // Ensure conversion table is in ascending order + assert(_countof(g_ConvertTable) > 0); + DXGI_FORMAT lastvalue = g_ConvertTable[0].format; + for (size_t index = 1; index < _countof(g_ConvertTable); ++index) + { + assert(g_ConvertTable[index].format > lastvalue); + lastvalue = g_ConvertTable[index].format; + } +#endif + + ConvertData key = { format, 0 }; + const ConvertData* in = (const ConvertData*)bsearch_s(&key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData), + _ConvertCompare, nullptr); + return (in) ? in->flags : 0; +} + +_Use_decl_annotations_ +void DirectX::_ConvertScanline( + XMVECTOR* pBuffer, + size_t count, + DXGI_FORMAT outFormat, + DXGI_FORMAT inFormat, + DWORD flags) +{ + assert(pBuffer && count > 0 && (((uintptr_t)pBuffer & 0xF) == 0)); + assert(IsValid(outFormat) && !IsTypeless(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat)); + assert(IsValid(inFormat) && !IsTypeless(inFormat) && !IsPlanar(inFormat) && !IsPalettized(inFormat)); + + if (!pBuffer) + return; + +#ifdef _DEBUG + // Ensure conversion table is in ascending order + assert(_countof(g_ConvertTable) > 0); + DXGI_FORMAT lastvalue = g_ConvertTable[0].format; + for (size_t index = 1; index < _countof(g_ConvertTable); ++index) + { + assert(g_ConvertTable[index].format > lastvalue); + lastvalue = g_ConvertTable[index].format; + } +#endif + + // Determine conversion details about source and dest formats + ConvertData key = { inFormat, 0 }; + const ConvertData* in = (const ConvertData*)bsearch_s(&key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData), + _ConvertCompare, nullptr); + key.format = outFormat; + const ConvertData* out = (const ConvertData*)bsearch_s(&key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData), + _ConvertCompare, nullptr); + if (!in || !out) + { + assert(false); + return; + } + + assert(_GetConvertFlags(inFormat) == in->flags); + assert(_GetConvertFlags(outFormat) == out->flags); + + // Handle SRGB filtering modes + switch (inFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + flags |= TEX_FILTER_SRGB_IN; + break; + + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + flags &= ~TEX_FILTER_SRGB_IN; + break; + + default: + break; + } + + switch (outFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + flags |= TEX_FILTER_SRGB_OUT; + break; + + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + flags &= ~TEX_FILTER_SRGB_OUT; + break; + + default: + break; + } + + if ((flags & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) + { + flags &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT); + } + + // sRGB input processing (sRGB -> Linear RGB) + if (flags & TEX_FILTER_SRGB_IN) + { + if (!(in->flags & CONVF_DEPTH) && ((in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM))) + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i, ++ptr) + { + *ptr = XMColorSRGBToRGB(*ptr); + } + } + } + + // Handle conversion special cases + DWORD diffFlags = in->flags ^ out->flags; + if (diffFlags != 0) + { + if (diffFlags & CONVF_DEPTH) + { + //--- Depth conversions --- + if (in->flags & CONVF_DEPTH) + { + // CONVF_DEPTH -> !CONVF_DEPTH + if (in->flags & CONVF_STENCIL) + { + // Stencil -> Alpha + static const XMVECTORF32 S = { { { 1.f, 1.f, 1.f, 255.f } } }; + + if (out->flags & CONVF_UNORM) + { + // UINT -> UNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatY(v); + v1 = XMVectorClamp(v1, g_XMZero, S); + v1 = XMVectorDivide(v1, S); + *ptr++ = XMVectorSelect(v1, v, g_XMSelect1110); + } + } + else if (out->flags & CONVF_SNORM) + { + // UINT -> SNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatY(v); + v1 = XMVectorClamp(v1, g_XMZero, S); + v1 = XMVectorDivide(v1, S); + v1 = XMVectorMultiplyAdd(v1, g_XMTwo, g_XMNegativeOne); + *ptr++ = XMVectorSelect(v1, v, g_XMSelect1110); + } + } + else + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatY(v); + *ptr++ = XMVectorSelect(v1, v, g_XMSelect1110); + } + } + } + + // Depth -> RGB + if ((out->flags & CONVF_UNORM) && (in->flags & CONVF_FLOAT)) + { + // Depth FLOAT -> UNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSaturate(v); + v1 = XMVectorSplatX(v1); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + else if (out->flags & CONVF_SNORM) + { + if (in->flags & CONVF_UNORM) + { + // Depth UNORM -> SNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne); + v1 = XMVectorSplatX(v1); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + else + { + // Depth FLOAT -> SNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorClamp(v, g_XMNegativeOne, g_XMOne); + v1 = XMVectorSplatX(v1); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + } + else + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatX(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + } + else + { + // !CONVF_DEPTH -> CONVF_DEPTH + + // RGB -> Depth (red channel) + switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) + { + case TEX_FILTER_RGB_COPY_GREEN: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatY(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + break; + + case TEX_FILTER_RGB_COPY_BLUE: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatZ(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + break; + + default: + if ((in->flags & CONVF_UNORM) && ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B))) + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVector3Dot(v, g_Grayscale); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + break; + } + + __fallthrough; + + case TEX_FILTER_RGB_COPY_RED: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatX(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + break; + } + + // Finialize type conversion for depth (red channel) + if (out->flags & CONVF_UNORM) + { + if (in->flags & CONVF_SNORM) + { + // SNORM -> UNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + else if (in->flags & CONVF_FLOAT) + { + // FLOAT -> UNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSaturate(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + } + + if (out->flags & CONVF_STENCIL) + { + // Alpha -> Stencil (green channel) + static const XMVECTORU32 select0100 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 } } }; + static const XMVECTORF32 S = { { { 255.f, 255.f, 255.f, 255.f } } }; + + if (in->flags & CONVF_UNORM) + { + // UNORM -> UINT + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorMultiply(v, S); + v1 = XMVectorSplatW(v1); + *ptr++ = XMVectorSelect(v, v1, select0100); + } + } + else if (in->flags & CONVF_SNORM) + { + // SNORM -> UINT + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf); + v1 = XMVectorMultiply(v1, S); + v1 = XMVectorSplatW(v1); + *ptr++ = XMVectorSelect(v, v1, select0100); + } + } + else + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatW(v); + *ptr++ = XMVectorSelect(v, v1, select0100); + } + } + } + } + } + else if (out->flags & CONVF_DEPTH) + { + // CONVF_DEPTH -> CONVF_DEPTH + if (diffFlags & CONVF_FLOAT) + { + if (in->flags & CONVF_FLOAT) + { + // FLOAT -> UNORM depth, preserve stencil + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSaturate(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + } + } + else if (out->flags & CONVF_UNORM) + { + //--- Converting to a UNORM --- + if (in->flags & CONVF_SNORM) + { + // SNORM -> UNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf); + } + } + else if (in->flags & CONVF_FLOAT) + { + XMVECTOR* ptr = pBuffer; + if (!(in->flags & CONVF_POS_ONLY) && (flags & TEX_FILTER_FLOAT_X2BIAS)) + { + // FLOAT -> UNORM (x2 bias) + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + v = XMVectorClamp(v, g_XMNegativeOne, g_XMOne); + *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf); + } + } + else + { + // FLOAT -> UNORM + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorSaturate(v); + } + } + } + } + else if (out->flags & CONVF_SNORM) + { + //--- Converting to a SNORM --- + if (in->flags & CONVF_UNORM) + { + // UNORM -> SNORM + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne); + } + } + else if (in->flags & CONVF_FLOAT) + { + XMVECTOR* ptr = pBuffer; + if ((in->flags & CONVF_POS_ONLY) && (flags & TEX_FILTER_FLOAT_X2BIAS)) + { + // FLOAT (positive only, x2 bias) -> SNORM + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + v = XMVectorSaturate(v); + *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne); + } + } + else + { + // FLOAT -> SNORM + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorClamp(v, g_XMNegativeOne, g_XMOne); + } + } + } + } + else if (diffFlags & CONVF_UNORM) + { + //--- Converting from a UNORM --- + assert(in->flags & CONVF_UNORM); + if (out->flags & CONVF_FLOAT) + { + if (!(out->flags & CONVF_POS_ONLY) && (flags & TEX_FILTER_FLOAT_X2BIAS)) + { + // UNORM (x2 bias) -> FLOAT + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne); + } + } + } + } + else if (diffFlags & CONVF_POS_ONLY) + { + if (flags & TEX_FILTER_FLOAT_X2BIAS) + { + if (in->flags & CONVF_POS_ONLY) + { + if (out->flags & CONVF_FLOAT) + { + // FLOAT (positive only, x2 bias) -> FLOAT + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + v = XMVectorSaturate(v); + *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne); + } + } + } + else if (out->flags & CONVF_POS_ONLY) + { + if (in->flags & CONVF_FLOAT) + { + // FLOAT -> FLOAT (positive only, x2 bias) + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + v = XMVectorClamp(v, g_XMNegativeOne, g_XMOne); + *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf); + } + } + else if (in->flags & CONVF_SNORM) + { + // SNORM -> FLOAT (positive only, x2 bias) + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf); + } + } + } + } + } + + // !CONVF_A -> CONVF_A is handled because LoadScanline ensures alpha defaults to 1.0 for no-alpha formats + + // CONVF_PACKED cases are handled because LoadScanline/StoreScanline handles packing/unpacking + + if (((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A)) + { + // !CONVF_A -> A format + switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) + { + case TEX_FILTER_RGB_COPY_GREEN: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorSplatY(v); + } + } + break; + + case TEX_FILTER_RGB_COPY_BLUE: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorSplatZ(v); + } + } + break; + + default: + if ((in->flags & CONVF_UNORM) && ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B))) + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVector3Dot(v, g_Grayscale); + } + break; + } + + __fallthrough; + + case TEX_FILTER_RGB_COPY_RED: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorSplatX(v); + } + } + break; + } + } + else if (((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A)) + { + // A format -> !CONVF_A + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + *ptr++ = XMVectorSplatW(v); + } + } + else if ((in->flags & CONVF_RGB_MASK) == CONVF_R) + { + if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B)) + { + // R format -> RGB format + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatX(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + else if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G)) + { + // R format -> RG format + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatX(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } + } + } + else if ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B)) + { + if ((out->flags & CONVF_RGB_MASK) == CONVF_R) + { + // RGB format -> R format + switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) + { + case TEX_FILTER_RGB_COPY_GREEN: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatY(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + break; + + case TEX_FILTER_RGB_COPY_BLUE: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSplatZ(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + break; + + default: + if (in->flags & CONVF_UNORM) + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVector3Dot(v, g_Grayscale); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + break; + } + + __fallthrough; + + case TEX_FILTER_RGB_COPY_RED: + // Leave data unchanged and the store will handle this... + break; + } + } + else if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G)) + { + // RGB format -> RG format + switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) + { + case TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_BLUE: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSwizzle<0, 2, 0, 2>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } + } + break; + + case TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + XMVECTOR v = *ptr; + XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } + } + break; + + case TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN: + default: + // Leave data unchanged and the store will handle this... + break; + } + } + } + } + + // sRGB output processing (Linear RGB -> sRGB) + if (flags & TEX_FILTER_SRGB_OUT) + { + if (!(out->flags & CONVF_DEPTH) && ((out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM))) + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i, ++ptr) + { + *ptr = XMColorRGBToSRGB(*ptr); + } + } + } +} + + +//------------------------------------------------------------------------------------- +// Dithering +//------------------------------------------------------------------------------------- +namespace +{ + // 4X4X4 ordered dithering matrix + const float g_Dither[] = + { + // (z & 3) + ( (y & 3) * 8) + (x & 3) + 0.468750f, -0.031250f, 0.343750f, -0.156250f, 0.468750f, -0.031250f, 0.343750f, -0.156250f, + -0.281250f, 0.218750f, -0.406250f, 0.093750f, -0.281250f, 0.218750f, -0.406250f, 0.093750f, + 0.281250f, -0.218750f, 0.406250f, -0.093750f, 0.281250f, -0.218750f, 0.406250f, -0.093750f, + -0.468750f, 0.031250f, -0.343750f, 0.156250f, -0.468750f, 0.031250f, -0.343750f, 0.156250f, + }; + + const XMVECTORF32 g_Scale16pc = { { { 65535.f, 65535.f, 65535.f, 65535.f } } }; + const XMVECTORF32 g_Scale15pc = { { { 32767.f, 32767.f, 32767.f, 32767.f } } }; + const XMVECTORF32 g_Scale10pc = { { { 1023.f, 1023.f, 1023.f, 3.f } } }; + const XMVECTORF32 g_Scale9pc = { { { 511.f, 511.f, 511.f, 3.f } } }; + const XMVECTORF32 g_Scale8pc = { { { 255.f, 255.f, 255.f, 255.f } } }; + const XMVECTORF32 g_Scale7pc = { { { 127.f, 127.f, 127.f, 127.f } } }; + const XMVECTORF32 g_Scale565pc = { { { 31.f, 63.f, 31.f, 1.f } } }; + const XMVECTORF32 g_Scale5551pc = { { { 31.f, 31.f, 31.f, 1.f } } }; + const XMVECTORF32 g_Scale4pc = { { { 15.f, 15.f, 15.f, 15.f } } }; + + const XMVECTORF32 g_ErrorWeight3 = { { { 3.f / 16.f, 3.f / 16.f, 3.f / 16.f, 3.f / 16.f } } }; + const XMVECTORF32 g_ErrorWeight5 = { { { 5.f / 16.f, 5.f / 16.f, 5.f / 16.f, 5.f / 16.f } } }; + const XMVECTORF32 g_ErrorWeight1 = { { { 1.f / 16.f, 1.f / 16.f, 1.f / 16.f, 1.f / 16.f } } }; + const XMVECTORF32 g_ErrorWeight7 = { { { 7.f / 16.f, 7.f / 16.f, 7.f / 16.f, 7.f / 16.f } } }; + +#define STORE_SCANLINE( type, scalev, clampzero, norm, itype, mask, row, bgr ) \ + if ( size >= sizeof(type) ) \ + { \ + type * __restrict dest = reinterpret_cast(pDestination); \ + for( size_t i = 0; i < count; ++i ) \ + { \ + ptrdiff_t index = static_cast( ( row & 1 ) ? ( count - i - 1 ) : i ); \ + ptrdiff_t delta = ( row & 1 ) ? -2 : 0; \ + \ + XMVECTOR v = sPtr[ index ]; \ + if ( bgr ) { v = XMVectorSwizzle<2, 1, 0, 3>( v ); } \ + if ( norm && clampzero ) v = XMVectorSaturate( v ) ; \ + else if ( clampzero ) v = XMVectorClamp( v, g_XMZero, scalev ); \ + else if ( norm ) v = XMVectorClamp( v, g_XMNegativeOne, g_XMOne ); \ + else v = XMVectorClamp( v, -scalev + g_XMOne, scalev ); \ + v = XMVectorAdd( v, vError ); \ + if ( norm ) v = XMVectorMultiply( v, scalev ); \ + \ + XMVECTOR target; \ + if ( pDiffusionErrors ) \ + { \ + target = XMVectorRound( v ); \ + vError = XMVectorSubtract( v, target ); \ + if (norm) vError = XMVectorDivide( vError, scalev ); \ + \ + /* Distribute error to next scanline and next pixel */ \ + pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError ); \ + pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError ); \ + pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError ); \ + vError = XMVectorMultiply( vError, g_ErrorWeight7 ); \ + } \ + else \ + { \ + /* Applied ordered dither */ \ + target = XMVectorAdd( v, ordered[ index & 3 ] ); \ + target = XMVectorRound( target ); \ + } \ + \ + target = XMVectorMin( scalev, target ); \ + target = XMVectorMax( (clampzero) ? g_XMZero : ( -scalev + g_XMOne ), target ); \ + \ + XMFLOAT4A tmp; \ + XMStoreFloat4A( &tmp, target ); \ + \ + auto dPtr = &dest[ index ]; \ + if (dPtr >= ePtr) break; \ + dPtr->x = static_cast( tmp.x ) & mask; \ + dPtr->y = static_cast( tmp.y ) & mask; \ + dPtr->z = static_cast( tmp.z ) & mask; \ + dPtr->w = static_cast( tmp.w ) & mask; \ + } \ + return true; \ + } \ + return false; + +#define STORE_SCANLINE2( type, scalev, clampzero, norm, itype, mask, row ) \ + /* The 2 component cases are always bgr=false */ \ + if ( size >= sizeof(type) ) \ + { \ + type * __restrict dest = reinterpret_cast(pDestination); \ + for( size_t i = 0; i < count; ++i ) \ + { \ + ptrdiff_t index = static_cast( ( row & 1 ) ? ( count - i - 1 ) : i ); \ + ptrdiff_t delta = ( row & 1 ) ? -2 : 0; \ + \ + XMVECTOR v = sPtr[ index ]; \ + if ( norm && clampzero ) v = XMVectorSaturate( v ) ; \ + else if ( clampzero ) v = XMVectorClamp( v, g_XMZero, scalev ); \ + else if ( norm ) v = XMVectorClamp( v, g_XMNegativeOne, g_XMOne ); \ + else v = XMVectorClamp( v, -scalev + g_XMOne, scalev ); \ + v = XMVectorAdd( v, vError ); \ + if ( norm ) v = XMVectorMultiply( v, scalev ); \ + \ + XMVECTOR target; \ + if ( pDiffusionErrors ) \ + { \ + target = XMVectorRound( v ); \ + vError = XMVectorSubtract( v, target ); \ + if (norm) vError = XMVectorDivide( vError, scalev ); \ + \ + /* Distribute error to next scanline and next pixel */ \ + pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError ); \ + pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError ); \ + pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError ); \ + vError = XMVectorMultiply( vError, g_ErrorWeight7 ); \ + } \ + else \ + { \ + /* Applied ordered dither */ \ + target = XMVectorAdd( v, ordered[ index & 3 ] ); \ + target = XMVectorRound( target ); \ + } \ + \ + target = XMVectorMin( scalev, target ); \ + target = XMVectorMax( (clampzero) ? g_XMZero : ( -scalev + g_XMOne ), target ); \ + \ + XMFLOAT4A tmp; \ + XMStoreFloat4A( &tmp, target ); \ + \ + auto dPtr = &dest[ index ]; \ + if (dPtr >= ePtr) break; \ + dPtr->x = static_cast( tmp.x ) & mask; \ + dPtr->y = static_cast( tmp.y ) & mask; \ + } \ + return true; \ + } \ + return false; + +#define STORE_SCANLINE1( type, scalev, clampzero, norm, mask, row, selectw ) \ + /* The 1 component cases are always bgr=false */ \ + if ( size >= sizeof(type) ) \ + { \ + type * __restrict dest = reinterpret_cast(pDestination); \ + for( size_t i = 0; i < count; ++i ) \ + { \ + ptrdiff_t index = static_cast( ( row & 1 ) ? ( count - i - 1 ) : i ); \ + ptrdiff_t delta = ( row & 1 ) ? -2 : 0; \ + \ + XMVECTOR v = sPtr[ index ]; \ + if ( norm && clampzero ) v = XMVectorSaturate( v ) ; \ + else if ( clampzero ) v = XMVectorClamp( v, g_XMZero, scalev ); \ + else if ( norm ) v = XMVectorClamp( v, g_XMNegativeOne, g_XMOne ); \ + else v = XMVectorClamp( v, -scalev + g_XMOne, scalev ); \ + v = XMVectorAdd( v, vError ); \ + if ( norm ) v = XMVectorMultiply( v, scalev ); \ + \ + XMVECTOR target; \ + if ( pDiffusionErrors ) \ + { \ + target = XMVectorRound( v ); \ + vError = XMVectorSubtract( v, target ); \ + if (norm) vError = XMVectorDivide( vError, scalev ); \ + \ + /* Distribute error to next scanline and next pixel */ \ + pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError ); \ + pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError ); \ + pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError ); \ + vError = XMVectorMultiply( vError, g_ErrorWeight7 ); \ + } \ + else \ + { \ + /* Applied ordered dither */ \ + target = XMVectorAdd( v, ordered[ index & 3 ] ); \ + target = XMVectorRound( target ); \ + } \ + \ + target = XMVectorMin( scalev, target ); \ + target = XMVectorMax( (clampzero) ? g_XMZero : ( -scalev + g_XMOne ), target ); \ + \ + auto dPtr = &dest[ index ]; \ + if (dPtr >= ePtr) break; \ + *dPtr = static_cast( (selectw) ? XMVectorGetW( target ) : XMVectorGetX( target ) ) & mask; \ + } \ + return true; \ + } \ + return false; +} + +#pragma warning(push) +#pragma warning( disable : 4127 ) + +_Use_decl_annotations_ +bool DirectX::_StoreScanlineDither( + void* pDestination, + size_t size, + DXGI_FORMAT format, + XMVECTOR* pSource, + size_t count, + float threshold, + size_t y, + size_t z, + XMVECTOR* pDiffusionErrors) +{ + assert(pDestination && size > 0); + assert(pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0)); + assert(IsValid(format) && !IsTypeless(format) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format)); + + XMVECTOR ordered[4]; + if (pDiffusionErrors) + { + // If pDiffusionErrors != 0, then this function performs error diffusion dithering (aka Floyd-Steinberg dithering) + + // To avoid the need for another temporary scanline buffer, we allow this function to overwrite the source buffer in-place + // Given the intended usage in the conversion routines, this is not a problem. + + XMVECTOR* ptr = pSource; + const XMVECTOR* err = pDiffusionErrors + 1; + for (size_t i = 0; i < count; ++i) + { + // Add contribution from previous scanline + XMVECTOR v = XMVectorAdd(*ptr, *err++); + *ptr++ = v; + } + + // Reset errors for next scanline + memset(pDiffusionErrors, 0, sizeof(XMVECTOR)*(count + 2)); + } + else + { + // If pDiffusionErrors == 0, then this function performs ordered dithering + + XMVECTOR dither = XMLoadFloat4(reinterpret_cast(g_Dither + (z & 3) + ((y & 3) * 8))); + + ordered[0] = XMVectorSplatX(dither); + ordered[1] = XMVectorSplatY(dither); + ordered[2] = XMVectorSplatZ(dither); + ordered[3] = XMVectorSplatW(dither); + } + + const XMVECTOR* __restrict sPtr = pSource; + if (!sPtr) + return false; + + const void* ePtr = reinterpret_cast(pDestination) + size; + + XMVECTOR vError = XMVectorZero(); + + switch (static_cast(format)) + { + case DXGI_FORMAT_R16G16B16A16_UNORM: + STORE_SCANLINE(XMUSHORTN4, g_Scale16pc, true, true, uint16_t, 0xFFFF, y, false) + + case DXGI_FORMAT_R16G16B16A16_UINT: + STORE_SCANLINE(XMUSHORT4, g_Scale16pc, true, false, uint16_t, 0xFFFF, y, false) + + case DXGI_FORMAT_R16G16B16A16_SNORM: + STORE_SCANLINE(XMSHORTN4, g_Scale15pc, false, true, int16_t, 0xFFFF, y, false) + + case DXGI_FORMAT_R16G16B16A16_SINT: + STORE_SCANLINE(XMSHORT4, g_Scale15pc, false, false, int16_t, 0xFFFF, y, false) + + case DXGI_FORMAT_R10G10B10A2_UNORM: + STORE_SCANLINE(XMUDECN4, g_Scale10pc, true, true, uint16_t, 0x3FF, y, false) + + case DXGI_FORMAT_R10G10B10A2_UINT: + STORE_SCANLINE(XMUDEC4, g_Scale10pc, true, false, uint16_t, 0x3FF, y, false) + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + if (size >= sizeof(XMUDEC4)) + { + static const XMVECTORF32 Scale = { { { 510.0f, 510.0f, 510.0f, 3.0f } } }; + static const XMVECTORF32 Bias = { { { 384.0f, 384.0f, 384.0f, 0.0f } } }; + static const XMVECTORF32 MinXR = { { { -0.7529f, -0.7529f, -0.7529f, 0.f } } }; + static const XMVECTORF32 MaxXR = { { { 1.2529f, 1.2529f, 1.2529f, 1.0f } } }; + + XMUDEC4 * __restrict dest = reinterpret_cast(pDestination); + for (size_t i = 0; i < count; ++i) + { + ptrdiff_t index = static_cast((y & 1) ? (count - i - 1) : i); + ptrdiff_t delta = (y & 1) ? -2 : 0; + + XMVECTOR v = XMVectorClamp(sPtr[index], MinXR, MaxXR); + v = XMVectorMultiplyAdd(v, Scale, vError); + + XMVECTOR target; + if (pDiffusionErrors) + { + target = XMVectorRound(v); + vError = XMVectorSubtract(v, target); + vError = XMVectorDivide(vError, Scale); + + // Distribute error to next scanline and next pixel + pDiffusionErrors[index - delta] += XMVectorMultiply(g_ErrorWeight3, vError); + pDiffusionErrors[index + 1] += XMVectorMultiply(g_ErrorWeight5, vError); + pDiffusionErrors[index + 2 + delta] += XMVectorMultiply(g_ErrorWeight1, vError); + vError = XMVectorMultiply(vError, g_ErrorWeight7); + } + else + { + // Applied ordered dither + target = XMVectorAdd(v, ordered[index & 3]); + target = XMVectorRound(target); + } + + target = XMVectorAdd(target, Bias); + target = XMVectorClamp(target, g_XMZero, g_Scale10pc); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, target); + + auto dPtr = &dest[index]; + if (dPtr >= ePtr) break; + dPtr->x = static_cast(tmp.x) & 0x3FF; + dPtr->y = static_cast(tmp.y) & 0x3FF; + dPtr->z = static_cast(tmp.z) & 0x3FF; + dPtr->w = static_cast(tmp.w); + } + return true; + } + return false; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + STORE_SCANLINE(XMUBYTEN4, g_Scale8pc, true, true, uint8_t, 0xFF, y, false) + + case DXGI_FORMAT_R8G8B8A8_UINT: + STORE_SCANLINE(XMUBYTE4, g_Scale8pc, true, false, uint8_t, 0xFF, y, false) + + case DXGI_FORMAT_R8G8B8A8_SNORM: + STORE_SCANLINE(XMBYTEN4, g_Scale7pc, false, true, int8_t, 0xFF, y, false) + + case DXGI_FORMAT_R8G8B8A8_SINT: + STORE_SCANLINE(XMBYTE4, g_Scale7pc, false, false, int8_t, 0xFF, y, false) + + case DXGI_FORMAT_R16G16_UNORM: + STORE_SCANLINE2(XMUSHORTN2, g_Scale16pc, true, true, uint16_t, 0xFFFF, y) + + case DXGI_FORMAT_R16G16_UINT: + STORE_SCANLINE2(XMUSHORT2, g_Scale16pc, true, false, uint16_t, 0xFFFF, y) + + case DXGI_FORMAT_R16G16_SNORM: + STORE_SCANLINE2(XMSHORTN2, g_Scale15pc, false, true, int16_t, 0xFFFF, y) + + case DXGI_FORMAT_R16G16_SINT: + STORE_SCANLINE2(XMSHORT2, g_Scale15pc, false, false, int16_t, 0xFFFF, y) + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + if (size >= sizeof(uint32_t)) + { + static const XMVECTORF32 Clamp = { { { 1.f, 255.f, 0.f, 0.f } } }; + static const XMVECTORF32 Scale = { { { 16777215.f, 1.f, 0.f, 0.f } } }; + static const XMVECTORF32 Scale2 = { { { 16777215.f, 255.f, 0.f, 0.f } } }; + + uint32_t * __restrict dest = reinterpret_cast(pDestination); + for (size_t i = 0; i < count; ++i) + { + ptrdiff_t index = static_cast((y & 1) ? (count - i - 1) : i); + ptrdiff_t delta = (y & 1) ? -2 : 0; + + XMVECTOR v = XMVectorClamp(sPtr[index], g_XMZero, Clamp); + v = XMVectorAdd(v, vError); + v = XMVectorMultiply(v, Scale); + + XMVECTOR target; + if (pDiffusionErrors) + { + target = XMVectorRound(v); + vError = XMVectorSubtract(v, target); + vError = XMVectorDivide(vError, Scale); + + // Distribute error to next scanline and next pixel + pDiffusionErrors[index - delta] += XMVectorMultiply(g_ErrorWeight3, vError); + pDiffusionErrors[index + 1] += XMVectorMultiply(g_ErrorWeight5, vError); + pDiffusionErrors[index + 2 + delta] += XMVectorMultiply(g_ErrorWeight1, vError); + vError = XMVectorMultiply(vError, g_ErrorWeight7); + } + else + { + // Applied ordered dither + target = XMVectorAdd(v, ordered[index & 3]); + target = XMVectorRound(target); + } + + target = XMVectorClamp(target, g_XMZero, Scale2); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, target); + + auto dPtr = &dest[index]; + if (dPtr >= ePtr) break; + *dPtr = (static_cast(tmp.x) & 0xFFFFFF) + | ((static_cast(tmp.y) & 0xFF) << 24); + } + return true; + } + return false; + + case DXGI_FORMAT_R8G8_UNORM: + STORE_SCANLINE2(XMUBYTEN2, g_Scale8pc, true, true, uint8_t, 0xFF, y) + + case DXGI_FORMAT_R8G8_UINT: + STORE_SCANLINE2(XMUBYTE2, g_Scale8pc, true, false, uint8_t, 0xFF, y) + + case DXGI_FORMAT_R8G8_SNORM: + STORE_SCANLINE2(XMBYTEN2, g_Scale7pc, false, true, int8_t, 0xFF, y) + + case DXGI_FORMAT_R8G8_SINT: + STORE_SCANLINE2(XMBYTE2, g_Scale7pc, false, false, int8_t, 0xFF, y) + + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + STORE_SCANLINE1(uint16_t, g_Scale16pc, true, true, 0xFFFF, y, false) + + case DXGI_FORMAT_R16_UINT: + STORE_SCANLINE1(uint16_t, g_Scale16pc, true, false, 0xFFFF, y, false) + + case DXGI_FORMAT_R16_SNORM: + STORE_SCANLINE1(int16_t, g_Scale15pc, false, true, 0xFFFF, y, false) + + case DXGI_FORMAT_R16_SINT: + STORE_SCANLINE1(int16_t, g_Scale15pc, false, false, 0xFFFF, y, false) + + case DXGI_FORMAT_R8_UNORM: + STORE_SCANLINE1(uint8_t, g_Scale8pc, true, true, 0xFF, y, false) + + case DXGI_FORMAT_R8_UINT: + STORE_SCANLINE1(uint8_t, g_Scale8pc, true, false, 0xFF, y, false) + + case DXGI_FORMAT_R8_SNORM: + STORE_SCANLINE1(int8_t, g_Scale7pc, false, true, 0xFF, y, false) + + case DXGI_FORMAT_R8_SINT: + STORE_SCANLINE1(int8_t, g_Scale7pc, false, false, 0xFF, y, false) + + case DXGI_FORMAT_A8_UNORM: + STORE_SCANLINE1(uint8_t, g_Scale8pc, true, true, 0xFF, y, true) + + case DXGI_FORMAT_B5G6R5_UNORM: + if (size >= sizeof(XMU565)) + { + XMU565 * __restrict dest = reinterpret_cast(pDestination); + for (size_t i = 0; i < count; ++i) + { + ptrdiff_t index = static_cast((y & 1) ? (count - i - 1) : i); + ptrdiff_t delta = (y & 1) ? -2 : 0; + + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(sPtr[index]); + v = XMVectorSaturate(v); + v = XMVectorAdd(v, vError); + v = XMVectorMultiply(v, g_Scale565pc); + + XMVECTOR target; + if (pDiffusionErrors) + { + target = XMVectorRound(v); + vError = XMVectorSubtract(v, target); + vError = XMVectorDivide(vError, g_Scale565pc); + + // Distribute error to next scanline and next pixel + pDiffusionErrors[index - delta] += XMVectorMultiply(g_ErrorWeight3, vError); + pDiffusionErrors[index + 1] += XMVectorMultiply(g_ErrorWeight5, vError); + pDiffusionErrors[index + 2 + delta] += XMVectorMultiply(g_ErrorWeight1, vError); + vError = XMVectorMultiply(vError, g_ErrorWeight7); + } + else + { + // Applied ordered dither + target = XMVectorAdd(v, ordered[index & 3]); + target = XMVectorRound(target); + } + + target = XMVectorClamp(target, g_XMZero, g_Scale565pc); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, target); + + auto dPtr = &dest[index]; + if (dPtr >= ePtr) break; + dPtr->x = static_cast(tmp.x) & 0x1F; + dPtr->y = static_cast(tmp.y) & 0x3F; + dPtr->z = static_cast(tmp.z) & 0x1F; + } + return true; + } + return false; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + if (size >= sizeof(XMU555)) + { + XMU555 * __restrict dest = reinterpret_cast(pDestination); + for (size_t i = 0; i < count; ++i) + { + ptrdiff_t index = static_cast((y & 1) ? (count - i - 1) : i); + ptrdiff_t delta = (y & 1) ? -2 : 0; + + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(sPtr[index]); + v = XMVectorSaturate(v); + v = XMVectorAdd(v, vError); + v = XMVectorMultiply(v, g_Scale5551pc); + + XMVECTOR target; + if (pDiffusionErrors) + { + target = XMVectorRound(v); + vError = XMVectorSubtract(v, target); + vError = XMVectorDivide(vError, g_Scale5551pc); + + // Distribute error to next scanline and next pixel + pDiffusionErrors[index - delta] += XMVectorMultiply(g_ErrorWeight3, vError); + pDiffusionErrors[index + 1] += XMVectorMultiply(g_ErrorWeight5, vError); + pDiffusionErrors[index + 2 + delta] += XMVectorMultiply(g_ErrorWeight1, vError); + vError = XMVectorMultiply(vError, g_ErrorWeight7); + } + else + { + // Applied ordered dither + target = XMVectorAdd(v, ordered[index & 3]); + target = XMVectorRound(target); + } + + target = XMVectorClamp(target, g_XMZero, g_Scale5551pc); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, target); + + auto dPtr = &dest[index]; + if (dPtr >= ePtr) break; + dPtr->x = static_cast(tmp.x) & 0x1F; + dPtr->y = static_cast(tmp.y) & 0x1F; + dPtr->z = static_cast(tmp.z) & 0x1F; + dPtr->w = (XMVectorGetW(target) > threshold) ? 1 : 0; + } + return true; + } + return false; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + STORE_SCANLINE(XMUBYTEN4, g_Scale8pc, true, true, uint8_t, 0xFF, y, true) + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + if (size >= sizeof(XMUBYTEN4)) + { + XMUBYTEN4 * __restrict dest = reinterpret_cast(pDestination); + for (size_t i = 0; i < count; ++i) + { + ptrdiff_t index = static_cast((y & 1) ? (count - i - 1) : i); + ptrdiff_t delta = (y & 1) ? -2 : 0; + + XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>(sPtr[index]); + v = XMVectorSaturate(v); + v = XMVectorAdd(v, vError); + v = XMVectorMultiply(v, g_Scale8pc); + + XMVECTOR target; + if (pDiffusionErrors) + { + target = XMVectorRound(v); + vError = XMVectorSubtract(v, target); + vError = XMVectorDivide(vError, g_Scale8pc); + + // Distribute error to next scanline and next pixel + pDiffusionErrors[index - delta] += XMVectorMultiply(g_ErrorWeight3, vError); + pDiffusionErrors[index + 1] += XMVectorMultiply(g_ErrorWeight5, vError); + pDiffusionErrors[index + 2 + delta] += XMVectorMultiply(g_ErrorWeight1, vError); + vError = XMVectorMultiply(vError, g_ErrorWeight7); + } + else + { + // Applied ordered dither + target = XMVectorAdd(v, ordered[index & 3]); + target = XMVectorRound(target); + } + + target = XMVectorClamp(target, g_XMZero, g_Scale8pc); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, target); + + auto dPtr = &dest[index]; + if (dPtr >= ePtr) break; + dPtr->x = static_cast(tmp.x) & 0xFF; + dPtr->y = static_cast(tmp.y) & 0xFF; + dPtr->z = static_cast(tmp.z) & 0xFF; + dPtr->w = 0; + } + return true; + } + return false; + + case DXGI_FORMAT_B4G4R4A4_UNORM: + STORE_SCANLINE(XMUNIBBLE4, g_Scale4pc, true, true, uint8_t, 0xF, y, true) + + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + STORE_SCANLINE(XMXDECN4, g_Scale9pc, false, true, uint16_t, 0x3FF, y, false) + + case XBOX_DXGI_FORMAT_R4G4_UNORM: + if (size >= sizeof(uint8_t)) + { + uint8_t * __restrict dest = reinterpret_cast(pDestination); + for (size_t i = 0; i < count; ++i) + { + ptrdiff_t index = static_cast((y & 1) ? (count - i - 1) : i); + ptrdiff_t delta = (y & 1) ? -2 : 0; + + XMVECTOR v = XMVectorSaturate(sPtr[index]); + v = XMVectorAdd(v, vError); + v = XMVectorMultiply(v, g_Scale4pc); + + XMVECTOR target; + if (pDiffusionErrors) + { + target = XMVectorRound(v); + vError = XMVectorSubtract(v, target); + vError = XMVectorDivide(vError, g_Scale4pc); + + // Distribute error to next scanline and next pixel + pDiffusionErrors[index - delta] += XMVectorMultiply(g_ErrorWeight3, vError); + pDiffusionErrors[index + 1] += XMVectorMultiply(g_ErrorWeight5, vError); + pDiffusionErrors[index + 2 + delta] += XMVectorMultiply(g_ErrorWeight1, vError); + vError = XMVectorMultiply(vError, g_ErrorWeight7); + } + else + { + // Applied ordered dither + target = XMVectorAdd(v, ordered[index & 3]); + target = XMVectorRound(target); + } + + target = XMVectorClamp(target, g_XMZero, g_Scale4pc); + + XMFLOAT4A tmp; + XMStoreFloat4A(&tmp, target); + + auto dPtr = &dest[index]; + if (dPtr >= ePtr) break; + *dPtr = (static_cast(tmp.x) & 0xF) + | ((static_cast(tmp.y) & 0xF) << 4); + } + return true; + } + return false; + + default: + return _StoreScanline(pDestination, size, format, pSource, count, threshold); + } +} + +#pragma warning(pop) + +#undef STORE_SCANLINE +#undef STORE_SCANLINE2 +#undef STORE_SCANLINE1 + +namespace +{ + //------------------------------------------------------------------------------------- + // Selection logic for using WIC vs. our own routines + //------------------------------------------------------------------------------------- + inline bool UseWICConversion( + _In_ DWORD filter, + _In_ DXGI_FORMAT sformat, + _In_ DXGI_FORMAT tformat, + _Out_ WICPixelFormatGUID& pfGUID, + _Out_ WICPixelFormatGUID& targetGUID) + { + memcpy(&pfGUID, &GUID_NULL, sizeof(GUID)); + memcpy(&targetGUID, &GUID_NULL, sizeof(GUID)); + + if (filter & TEX_FILTER_FORCE_NON_WIC) + { + // Explicit flag indicates use of non-WIC code paths + return false; + } + + if (!_DXGIToWIC(sformat, pfGUID) || !_DXGIToWIC(tformat, targetGUID)) + { + // Source or target format are not WIC supported native pixel formats + return false; + } + + if (filter & TEX_FILTER_FORCE_WIC) + { + // Explicit flag to use WIC code paths, skips all the case checks below + return true; + } + + if (filter & TEX_FILTER_SEPARATE_ALPHA) + { + // Alpha is not premultiplied, so use non-WIC code paths + return false; + } + + if (filter & TEX_FILTER_FLOAT_X2BIAS) + { + // X2 Scale & Bias conversions not supported by WIC code paths + return false; + } + +#if defined(_XBOX_ONE) && defined(_TITLE) + if (sformat == DXGI_FORMAT_R16G16B16A16_FLOAT + || sformat == DXGI_FORMAT_R16_FLOAT + || tformat == DXGI_FORMAT_R16G16B16A16_FLOAT + || tformat == DXGI_FORMAT_R16_FLOAT) + { + // Use non-WIC code paths as these conversions are not supported by Xbox One XDK + return false; + } +#endif + + // Check for special cases + switch (sformat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + switch (tformat) + { + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_D32_FLOAT: + // WIC converts via UNORM formats and ends up converting colorspaces for these cases + case DXGI_FORMAT_A8_UNORM: + // Conversion logic for these kinds of textures is unintuitive for WIC code paths + return false; + + default: + break; + } + break; + + case DXGI_FORMAT_R16_FLOAT: + switch (tformat) + { + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_D32_FLOAT: + // WIC converts via UNORM formats and ends up converting colorspaces for these cases + case DXGI_FORMAT_A8_UNORM: + // Conversion logic for these kinds of textures is unintuitive for WIC code paths + return false; + + default: + break; + } + break; + + case DXGI_FORMAT_A8_UNORM: + // Conversion logic for these kinds of textures is unintuitive for WIC code paths + return false; + + default: + switch (tformat) + { + case DXGI_FORMAT_A8_UNORM: + // Conversion logic for these kinds of textures is unintuitive for WIC code paths + return false; + + default: + break; + } + } + + // Check for implicit color space changes + if (IsSRGB(sformat)) + filter |= TEX_FILTER_SRGB_IN; + + if (IsSRGB(tformat)) + filter |= TEX_FILTER_SRGB_OUT; + + if ((filter & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) + { + filter &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT); + } + + DWORD wicsrgb = _CheckWICColorSpace(pfGUID, targetGUID); + + if (wicsrgb != (filter & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT))) + { + // WIC will perform a colorspace conversion we didn't request + return false; + } + + return true; + } + + //------------------------------------------------------------------------------------- + // Convert the source image using WIC + //------------------------------------------------------------------------------------- + HRESULT ConvertUsingWIC( + _In_ const Image& srcImage, + _In_ const WICPixelFormatGUID& pfGUID, + _In_ const WICPixelFormatGUID& targetGUID, + _In_ DWORD filter, + _In_ float threshold, + _In_ const Image& destImage) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr FC; + HRESULT hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + // Note that WIC conversion ignores the TEX_FILTER_SRGB_IN and TEX_FILTER_SRGB_OUT flags, + // but also always assumes UNORM <-> FLOAT conversions are changing color spaces sRGB <-> scRGB + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfGUID, targetGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + // This case is not an issue for the subset of WIC formats that map directly to DXGI + return E_UNEXPECTED; + } + + ComPtr source; + hr = pWIC->CreateBitmapFromMemory(static_cast(srcImage.width), static_cast(srcImage.height), pfGUID, + static_cast(srcImage.rowPitch), static_cast(srcImage.slicePitch), + srcImage.pixels, source.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = FC->Initialize(source.Get(), targetGUID, _GetWICDither(filter), nullptr, threshold * 100.f, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(destImage.rowPitch), static_cast(destImage.slicePitch), destImage.pixels); + if (FAILED(hr)) + return hr; + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Convert the source image (not using WIC) + //------------------------------------------------------------------------------------- + HRESULT ConvertCustom( + _In_ const Image& srcImage, + _In_ DWORD filter, + _In_ const Image& destImage, + _In_ float threshold, + size_t z) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if (!pSrc || !pDest) + return E_POINTER; + + size_t width = srcImage.width; + + if (filter & TEX_FILTER_DITHER_DIFFUSION) + { + // Error diffusion dithering (aka Floyd-Steinberg dithering) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*(width * 2 + 2)), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* pDiffusionErrors = scanline.get() + width; + memset(pDiffusionErrors, 0, sizeof(XMVECTOR)*(width + 2)); + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format)) + return E_FAIL; + + _ConvertScanline(scanline.get(), width, destImage.format, srcImage.format, filter); + + if (!_StoreScanlineDither(pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold, h, z, pDiffusionErrors)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + } + else + { + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + if (filter & TEX_FILTER_DITHER) + { + // Ordered dithering + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format)) + return E_FAIL; + + _ConvertScanline(scanline.get(), width, destImage.format, srcImage.format, filter); + + if (!_StoreScanlineDither(pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold, h, z, nullptr)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + } + else + { + // No dithering + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format)) + return E_FAIL; + + _ConvertScanline(scanline.get(), width, destImage.format, srcImage.format, filter); + + if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + } + } + + return S_OK; + } + + //------------------------------------------------------------------------------------- + DXGI_FORMAT _PlanarToSingle(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_NV11: + return DXGI_FORMAT_YUY2; + + case DXGI_FORMAT_P010: + return DXGI_FORMAT_Y210; + + case DXGI_FORMAT_P016: + return DXGI_FORMAT_Y216; + + // We currently do not support conversion for Xbox One specific 16-bit depth formats + + // We can't do anything with DXGI_FORMAT_420_OPAQUE because it's an opaque blob of bits + + // We don't support conversion of JPEG Hardware decode formats + + default: + return DXGI_FORMAT_UNKNOWN; + } + } + + //------------------------------------------------------------------------------------- + // Convert the image from a planar to non-planar image + //------------------------------------------------------------------------------------- +#define CONVERT_420_TO_422( srcType, destType )\ + {\ + size_t rowPitch = srcImage.rowPitch;\ + \ + auto sourceE = reinterpret_cast( pSrc + srcImage.slicePitch );\ + auto pSrcUV = pSrc + ( srcImage.height * rowPitch );\ + \ + for( size_t y = 0; y < srcImage.height; y+= 2 )\ + {\ + auto sPtrY0 = reinterpret_cast( pSrc );\ + auto sPtrY2 = reinterpret_cast( pSrc + rowPitch );\ + auto sPtrUV = reinterpret_cast( pSrcUV );\ + \ + destType * __restrict dPtr0 = reinterpret_cast(pDest);\ + destType * __restrict dPtr1 = reinterpret_cast(pDest + destImage.rowPitch);\ + \ + for( size_t x = 0; x < srcImage.width; x+= 2 )\ + {\ + if ( (sPtrUV+1) >= sourceE ) break;\ + \ + srcType u = *(sPtrUV++);\ + srcType v = *(sPtrUV++);\ + \ + dPtr0->x = *(sPtrY0++);\ + dPtr0->y = u;\ + dPtr0->z = *(sPtrY0++);\ + dPtr0->w = v;\ + ++dPtr0;\ + \ + dPtr1->x = *(sPtrY2++);\ + dPtr1->y = u;\ + dPtr1->z = *(sPtrY2++);\ + dPtr1->w = v;\ + ++dPtr1;\ + }\ + \ + pSrc += rowPitch * 2;\ + pSrcUV += rowPitch;\ + \ + pDest += destImage.rowPitch * 2;\ + }\ + } + + HRESULT ConvertToSinglePlane_(_In_ const Image& srcImage, _In_ const Image& destImage) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if (!pSrc || !pDest) + return E_POINTER; + + switch (srcImage.format) + { + case DXGI_FORMAT_NV12: + assert(destImage.format == DXGI_FORMAT_YUY2); + CONVERT_420_TO_422(uint8_t, XMUBYTEN4); + return S_OK; + + case DXGI_FORMAT_P010: + assert(destImage.format == DXGI_FORMAT_Y210); + CONVERT_420_TO_422(uint16_t, XMUSHORTN4); + return S_OK; + + case DXGI_FORMAT_P016: + assert(destImage.format == DXGI_FORMAT_Y216); + CONVERT_420_TO_422(uint16_t, XMUSHORTN4); + return S_OK; + + case DXGI_FORMAT_NV11: + assert(destImage.format == DXGI_FORMAT_YUY2); + // Convert 4:1:1 to 4:2:2 + { + size_t rowPitch = srcImage.rowPitch; + + const uint8_t* sourceE = pSrc + srcImage.slicePitch; + const uint8_t* pSrcUV = pSrc + (srcImage.height * rowPitch); + + for (size_t y = 0; y < srcImage.height; ++y) + { + const uint8_t* sPtrY = pSrc; + const uint8_t* sPtrUV = pSrcUV; + + XMUBYTEN4 * __restrict dPtr = reinterpret_cast(pDest); + + for (size_t x = 0; x < srcImage.width; x += 4) + { + if ((sPtrUV + 1) >= sourceE) break; + + uint8_t u = *(sPtrUV++); + uint8_t v = *(sPtrUV++); + + dPtr->x = *(sPtrY++); + dPtr->y = u; + dPtr->z = *(sPtrY++); + dPtr->w = v; + ++dPtr; + + dPtr->x = *(sPtrY++); + dPtr->y = u; + dPtr->z = *(sPtrY++); + dPtr->w = v; + ++dPtr; + } + + pSrc += rowPitch; + pSrcUV += (rowPitch >> 1); + + pDest += destImage.rowPitch; + } + } + return S_OK; + + default: + return E_UNEXPECTED; + } + } + +#undef CONVERT_420_TO_422 +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Convert image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Convert( + const Image& srcImage, + DXGI_FORMAT format, + DWORD filter, + float threshold, + ScratchImage& image) +{ + if ((srcImage.format == format) || !IsValid(format)) + return E_INVALIDARG; + + if (!srcImage.pixels) + return E_POINTER; + + if (IsCompressed(srcImage.format) || IsCompressed(format) + || IsPlanar(srcImage.format) || IsPlanar(format) + || IsPalettized(srcImage.format) || IsPalettized(format) + || IsTypeless(srcImage.format) || IsTypeless(format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) + return E_INVALIDARG; + + HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *rimage = image.GetImage(0, 0, 0); + if (!rimage) + { + image.Release(); + return E_POINTER; + } + + WICPixelFormatGUID pfGUID, targetGUID; + if (UseWICConversion(filter, srcImage.format, format, pfGUID, targetGUID)) + { + hr = ConvertUsingWIC(srcImage, pfGUID, targetGUID, filter, threshold, *rimage); + } + else + { + hr = ConvertCustom(srcImage, filter, *rimage, threshold, 0); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Convert image (complex) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Convert( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DXGI_FORMAT format, + DWORD filter, + float threshold, + ScratchImage& result) +{ + if (!srcImages || !nimages || (metadata.format == format) || !IsValid(format)) + return E_INVALIDARG; + + if (IsCompressed(metadata.format) || IsCompressed(format) + || IsPlanar(metadata.format) || IsPlanar(format) + || IsPalettized(metadata.format) || IsPalettized(format) + || IsTypeless(metadata.format) || IsTypeless(format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX)) + return E_INVALIDARG; + + TexMetadata mdata2 = metadata; + mdata2.format = format; + HRESULT hr = result.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) + { + result.Release(); + return E_FAIL; + } + + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } + + WICPixelFormatGUID pfGUID, targetGUID; + bool usewic = !metadata.IsPMAlpha() && UseWICConversion(filter, metadata.format, format, pfGUID, targetGUID); + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + for (size_t index = 0; index < nimages; ++index) + { + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + { + result.Release(); + return E_FAIL; + } + + const Image& dst = dest[index]; + assert(dst.format == format); + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + if (usewic) + { + hr = ConvertUsingWIC(src, pfGUID, targetGUID, filter, threshold, dst); + } + else + { + hr = ConvertCustom(src, filter, dst, threshold, 0); + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + size_t index = 0; + size_t d = metadata.depth; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + for (size_t slice = 0; slice < d; ++slice, ++index) + { + if (index >= nimages) + { + result.Release(); + return E_FAIL; + } + + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + { + result.Release(); + return E_FAIL; + } + + const Image& dst = dest[index]; + assert(dst.format == format); + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + if (usewic) + { + hr = ConvertUsingWIC(src, pfGUID, targetGUID, filter, threshold, dst); + } + else + { + hr = ConvertCustom(src, filter, dst, threshold, slice); + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + result.Release(); + return E_FAIL; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Convert image from planar to single plane (image) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::ConvertToSinglePlane(const Image& srcImage, ScratchImage& image) +{ + if (!IsPlanar(srcImage.format)) + return E_INVALIDARG; + + if (!srcImage.pixels) + return E_POINTER; + + DXGI_FORMAT format = _PlanarToSingle(srcImage.format); + if (format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) + return E_INVALIDARG; + + HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *rimage = image.GetImage(0, 0, 0); + if (!rimage) + { + image.Release(); + return E_POINTER; + } + + hr = ConvertToSinglePlane_(srcImage, *rimage); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Convert image from planar to single plane (complex) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::ConvertToSinglePlane( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + ScratchImage& result) +{ + if (!srcImages || !nimages) + return E_INVALIDARG; + + if (metadata.IsVolumemap()) + { + // Direct3D does not support any planar formats for Texture3D + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + DXGI_FORMAT format = _PlanarToSingle(metadata.format); + if (format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX)) + return E_INVALIDARG; + + TexMetadata mdata2 = metadata; + mdata2.format = format; + HRESULT hr = result.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) + { + result.Release(); + return E_FAIL; + } + + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } + + for (size_t index = 0; index < nimages; ++index) + { + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + return E_FAIL; + + const Image& dst = dest[index]; + assert(dst.format == format); + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + hr = ConvertToSinglePlane_(src, dst); + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexD3D11.cpp b/Kits/DirectXTex/DirectXTexD3D11.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29f2dae7dde2a545027900353cc089c7352ebe11 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexD3D11.cpp @@ -0,0 +1,968 @@ +//------------------------------------------------------------------------------------- +// DirectXTexD3D11.cpp +// +// DirectX Texture Library - Direct3D 11 helpers +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#include +#endif + +#ifndef IID_GRAPHICS_PPV_ARGS +#define IID_GRAPHICS_PPV_ARGS(x) IID_PPV_ARGS(x) +#endif + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +static_assert(static_cast(TEX_DIMENSION_TEXTURE1D) == static_cast(D3D11_RESOURCE_DIMENSION_TEXTURE1D), "header enum mismatch"); +static_assert(static_cast(TEX_DIMENSION_TEXTURE2D) == static_cast(D3D11_RESOURCE_DIMENSION_TEXTURE2D), "header enum mismatch"); +static_assert(static_cast(TEX_DIMENSION_TEXTURE3D) == static_cast(D3D11_RESOURCE_DIMENSION_TEXTURE3D), "header enum mismatch"); + +namespace +{ + HRESULT Capture( + _In_ ID3D11DeviceContext* pContext, + _In_ ID3D11Resource* pSource, + const TexMetadata& metadata, + const ScratchImage& result) + { + if (!pContext || !pSource || !result.GetPixels()) + return E_POINTER; + +#if defined(_XBOX_ONE) && defined(_TITLE) + + ComPtr d3dDevice; + pContext->GetDevice(d3dDevice.GetAddressOf()); + + if (d3dDevice->GetCreationFlags() & D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS) + { + ComPtr d3dDeviceX; + HRESULT hr = d3dDevice.As(&d3dDeviceX); + if (FAILED(hr)) + return hr; + + ComPtr d3dContextX; + hr = pContext->QueryInterface(IID_GRAPHICS_PPV_ARGS(d3dContextX.GetAddressOf())); + if (FAILED(hr)) + return hr; + + UINT64 copyFence = d3dContextX->InsertFence(0); + + while (d3dDeviceX->IsFencePending(copyFence)) + { + SwitchToThread(); + } + } + +#endif + + if (metadata.IsVolumemap()) + { + //--- Volume texture ---------------------------------------------------------- + assert(metadata.arraySize == 1); + + size_t height = metadata.height; + size_t depth = metadata.depth; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + UINT dindex = D3D11CalcSubresource(static_cast(level), 0, static_cast(metadata.mipLevels)); + + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(pSource, dindex, D3D11_MAP_READ, 0, &mapped); + if (FAILED(hr)) + return hr; + + auto pslice = reinterpret_cast(mapped.pData); + if (!pslice) + { + pContext->Unmap(pSource, dindex); + return E_POINTER; + } + + size_t lines = ComputeScanlines(metadata.format, height); + if (!lines) + { + pContext->Unmap(pSource, dindex); + return E_UNEXPECTED; + } + + for (size_t slice = 0; slice < depth; ++slice) + { + const Image* img = result.GetImage(level, 0, slice); + if (!img) + { + pContext->Unmap(pSource, dindex); + return E_FAIL; + } + + if (!img->pixels) + { + pContext->Unmap(pSource, dindex); + return E_POINTER; + } + + const uint8_t* sptr = pslice; + uint8_t* dptr = img->pixels; + for (size_t h = 0; h < lines; ++h) + { + size_t msize = std::min(img->rowPitch, mapped.RowPitch); + memcpy_s(dptr, img->rowPitch, sptr, msize); + sptr += mapped.RowPitch; + dptr += img->rowPitch; + } + + pslice += mapped.DepthPitch; + } + + pContext->Unmap(pSource, dindex); + + if (height > 1) + height >>= 1; + if (depth > 1) + depth >>= 1; + } + } + else + { + //--- 1D or 2D texture -------------------------------------------------------- + assert(metadata.depth == 1); + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t height = metadata.height; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + UINT dindex = D3D11CalcSubresource(static_cast(level), static_cast(item), static_cast(metadata.mipLevels)); + + D3D11_MAPPED_SUBRESOURCE mapped; + HRESULT hr = pContext->Map(pSource, dindex, D3D11_MAP_READ, 0, &mapped); + if (FAILED(hr)) + return hr; + + const Image* img = result.GetImage(level, item, 0); + if (!img) + { + pContext->Unmap(pSource, dindex); + return E_FAIL; + } + + if (!img->pixels) + { + pContext->Unmap(pSource, dindex); + return E_POINTER; + } + + size_t lines = ComputeScanlines(metadata.format, height); + if (!lines) + { + pContext->Unmap(pSource, dindex); + return E_UNEXPECTED; + } + + auto sptr = reinterpret_cast(mapped.pData); + uint8_t* dptr = img->pixels; + for (size_t h = 0; h < lines; ++h) + { + size_t msize = std::min(img->rowPitch, mapped.RowPitch); + memcpy_s(dptr, img->rowPitch, sptr, msize); + sptr += mapped.RowPitch; + dptr += img->rowPitch; + } + + pContext->Unmap(pSource, dindex); + + if (height > 1) + height >>= 1; + } + } + } + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Determine if given texture metadata is supported on the given device +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::IsSupportedTexture( + ID3D11Device* pDevice, + const TexMetadata& metadata) +{ + if (!pDevice) + return false; + + D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel(); + + // Validate format + DXGI_FORMAT fmt = metadata.format; + + if (!IsValid(fmt)) + return false; + + switch (fmt) + { + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + if (fl < D3D_FEATURE_LEVEL_10_0) + return false; + break; + + 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: + if (fl < D3D_FEATURE_LEVEL_11_0) + return false; + break; + + default: + break; + } + + // Validate miplevel count + if (metadata.mipLevels > D3D11_REQ_MIP_LEVELS) + return false; + + // Validate array size, dimension, and width/height + size_t arraySize = metadata.arraySize; + size_t iWidth = metadata.width; + size_t iHeight = metadata.height; + size_t iDepth = metadata.depth; + + // Most cases are known apriori based on feature level, but we use this for robustness to handle the few optional cases + UINT formatSupport = 0; + HRESULT hr = pDevice->CheckFormatSupport(fmt, &formatSupport); + if (FAILED(hr)) + { + formatSupport = 0; + } + + if (metadata.mipLevels > 1 && !(formatSupport & D3D11_FORMAT_SUPPORT_MIP)) + { + return false; + } + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (!(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE1D)) + return false; + + if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURE1D_U_DIMENSION)) + return false; + + if (fl < D3D_FEATURE_LEVEL_11_0) + { + if ((arraySize > D3D10_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D10_REQ_TEXTURE1D_U_DIMENSION)) + return false; + + if (fl < D3D_FEATURE_LEVEL_10_0) + { + if ((arraySize > 1) || (iWidth > D3D_FL9_3_REQ_TEXTURE1D_U_DIMENSION)) + return false; + + if ((fl < D3D_FEATURE_LEVEL_9_3) && (iWidth > D3D_FL9_1_REQ_TEXTURE1D_U_DIMENSION)) + return false; + } + } + break; + + case TEX_DIMENSION_TEXTURE2D: + if (metadata.IsCubemap()) + { + if (!(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) + return false; + + if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D11_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D11_REQ_TEXTURECUBE_DIMENSION)) + return false; + + if (fl < D3D_FEATURE_LEVEL_11_0) + { + if ((arraySize > D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D10_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D10_REQ_TEXTURECUBE_DIMENSION)) + return false; + + if ((fl < D3D_FEATURE_LEVEL_10_1) && (arraySize != 6)) + return false; + + if (fl < D3D_FEATURE_LEVEL_10_0) + { + if ((iWidth > D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION)) + return false; + + if ((fl < D3D_FEATURE_LEVEL_9_3) + && ((iWidth > D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION) + || (iHeight > D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION))) + return false; + } + } + } + else // Not a cube map + { + if (!(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) + return false; + + 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 false; + + if (fl < D3D_FEATURE_LEVEL_11_0) + { + if ((arraySize > D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) + || (iWidth > D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION) + || (iHeight > D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + return false; + + if (fl < D3D_FEATURE_LEVEL_10_0) + { + if ((arraySize > 1) + || (iWidth > D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION) + || (iHeight > D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + return false; + + if ((fl < D3D_FEATURE_LEVEL_9_3) + && ((iWidth > D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION) + || (iHeight > D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION))) + return false; + } + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + if (!(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D)) + return false; + + 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 false; + + if (fl < D3D_FEATURE_LEVEL_11_0) + { + if ((iWidth > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iHeight > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iDepth > D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) + return false; + + if (fl < D3D_FEATURE_LEVEL_10_0) + { + if ((iWidth > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iHeight > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) + || (iDepth > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) + return false; + } + } + break; + + default: + // Not a supported dimension + return false; + } + + return true; +} + + +//------------------------------------------------------------------------------------- +// Create a texture resource +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateTexture( + ID3D11Device* pDevice, + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + ID3D11Resource** ppResource) +{ + return CreateTextureEx( + pDevice, srcImages, nimages, metadata, + D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false, + ppResource); +} + +_Use_decl_annotations_ +HRESULT DirectX::CreateTextureEx( + ID3D11Device* pDevice, + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + D3D11_USAGE usage, + unsigned int bindFlags, + unsigned int cpuAccessFlags, + unsigned int miscFlags, + bool forceSRGB, + ID3D11Resource** ppResource) +{ + if (!pDevice || !srcImages || !nimages || !ppResource) + return E_INVALIDARG; + + *ppResource = nullptr; + + if (!metadata.mipLevels || !metadata.arraySize) + return E_INVALIDARG; + + if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX) + || (metadata.mipLevels > UINT16_MAX) || (metadata.arraySize > UINT16_MAX)) + return E_INVALIDARG; + + std::unique_ptr initData(new (std::nothrow) D3D11_SUBRESOURCE_DATA[metadata.mipLevels * metadata.arraySize]); + if (!initData) + return E_OUTOFMEMORY; + + // Fill out subresource array + if (metadata.IsVolumemap()) + { + //--- Volume case ------------------------------------------------------------- + if (!metadata.depth) + return E_INVALIDARG; + + if (metadata.depth > UINT16_MAX) + return E_INVALIDARG; + + if (metadata.arraySize > 1) + // Direct3D 11 doesn't support arrays of 3D textures + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + size_t depth = metadata.depth; + + size_t idx = 0; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + size_t index = metadata.ComputeIndex(level, 0, 0); + if (index >= nimages) + return E_FAIL; + + const Image& img = srcImages[index]; + + if (img.format != metadata.format) + return E_FAIL; + + if (!img.pixels) + return E_POINTER; + + // Verify pixels in image 1 .. (depth-1) are exactly image->slicePitch apart + // For 3D textures, this relies on all slices of the same miplevel being continous in memory + // (this is how ScratchImage lays them out), which is why we just give the 0th slice to Direct3D 11 + const uint8_t* pSlice = img.pixels + img.slicePitch; + for (size_t slice = 1; slice < depth; ++slice) + { + size_t tindex = metadata.ComputeIndex(level, 0, slice); + if (tindex >= nimages) + return E_FAIL; + + const Image& timg = srcImages[tindex]; + + if (!timg.pixels) + return E_POINTER; + + if (timg.pixels != pSlice + || timg.format != metadata.format + || timg.rowPitch != img.rowPitch + || timg.slicePitch != img.slicePitch) + return E_FAIL; + + pSlice = timg.pixels + img.slicePitch; + } + + assert(idx < (metadata.mipLevels * metadata.arraySize)); + + initData[idx].pSysMem = img.pixels; + initData[idx].SysMemPitch = static_cast(img.rowPitch); + initData[idx].SysMemSlicePitch = static_cast(img.slicePitch); + ++idx; + + if (depth > 1) + depth >>= 1; + } + } + else + { + //--- 1D or 2D texture case --------------------------------------------------- + size_t idx = 0; + for (size_t item = 0; item < metadata.arraySize; ++item) + { + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + size_t index = metadata.ComputeIndex(level, item, 0); + if (index >= nimages) + return E_FAIL; + + const Image& img = srcImages[index]; + + if (img.format != metadata.format) + return E_FAIL; + + if (!img.pixels) + return E_POINTER; + + assert(idx < (metadata.mipLevels * metadata.arraySize)); + + initData[idx].pSysMem = img.pixels; + initData[idx].SysMemPitch = static_cast(img.rowPitch); + initData[idx].SysMemSlicePitch = static_cast(img.slicePitch); + ++idx; + } + } + } + + // Create texture using static initialization data + HRESULT hr = E_FAIL; + + DXGI_FORMAT tformat = (forceSRGB) ? MakeSRGB(metadata.format) : metadata.format; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + { + D3D11_TEXTURE1D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = tformat; + desc.Usage = usage; + desc.BindFlags = bindFlags; + desc.CPUAccessFlags = cpuAccessFlags; + desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; + + hr = pDevice->CreateTexture1D(&desc, initData.get(), reinterpret_cast(ppResource)); + } + break; + + case TEX_DIMENSION_TEXTURE2D: + { + D3D11_TEXTURE2D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = tformat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = usage; + desc.BindFlags = bindFlags; + desc.CPUAccessFlags = cpuAccessFlags; + if (metadata.IsCubemap()) + desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE; + else + desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; + + hr = pDevice->CreateTexture2D(&desc, initData.get(), reinterpret_cast(ppResource)); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + D3D11_TEXTURE3D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.Depth = static_cast(metadata.depth); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.Format = tformat; + desc.Usage = usage; + desc.BindFlags = bindFlags; + desc.CPUAccessFlags = cpuAccessFlags; + desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; + + hr = pDevice->CreateTexture3D(&desc, initData.get(), reinterpret_cast(ppResource)); + } + break; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Create a shader resource view and associated texture +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateShaderResourceView( + ID3D11Device* pDevice, + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + ID3D11ShaderResourceView** ppSRV) +{ + return CreateShaderResourceViewEx( + pDevice, srcImages, nimages, metadata, + D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false, + ppSRV); +} + +_Use_decl_annotations_ +HRESULT DirectX::CreateShaderResourceViewEx( + ID3D11Device* pDevice, + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + D3D11_USAGE usage, + unsigned int bindFlags, + unsigned int cpuAccessFlags, + unsigned int miscFlags, + bool forceSRGB, + ID3D11ShaderResourceView** ppSRV) +{ + if (!ppSRV) + return E_INVALIDARG; + + *ppSRV = nullptr; + + ComPtr resource; + HRESULT hr = CreateTextureEx(pDevice, srcImages, nimages, metadata, + usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, + resource.GetAddressOf()); + if (FAILED(hr)) + return hr; + + assert(resource); + + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; + if (forceSRGB) + SRVDesc.Format = MakeSRGB(metadata.format); + else + SRVDesc.Format = metadata.format; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (metadata.arraySize > 1) + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY; + SRVDesc.Texture1DArray.MipLevels = static_cast(metadata.mipLevels); + SRVDesc.Texture1DArray.ArraySize = static_cast(metadata.arraySize); + } + else + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MipLevels = static_cast(metadata.mipLevels); + } + break; + + case TEX_DIMENSION_TEXTURE2D: + if (metadata.IsCubemap()) + { + if (metadata.arraySize > 6) + { + assert((metadata.arraySize % 6) == 0); + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY; + SRVDesc.TextureCubeArray.MipLevels = static_cast(metadata.mipLevels); + SRVDesc.TextureCubeArray.NumCubes = static_cast(metadata.arraySize / 6); + } + else + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MipLevels = static_cast(metadata.mipLevels); + } + } + else if (metadata.arraySize > 1) + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; + SRVDesc.Texture2DArray.MipLevels = static_cast(metadata.mipLevels); + SRVDesc.Texture2DArray.ArraySize = static_cast(metadata.arraySize); + } + else + { + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = static_cast(metadata.mipLevels); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + assert(metadata.arraySize == 1); + SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MipLevels = static_cast(metadata.mipLevels); + break; + + default: + return E_FAIL; + } + + hr = pDevice->CreateShaderResourceView(resource.Get(), &SRVDesc, ppSRV); + if (FAILED(hr)) + return hr; + + assert(*ppSRV); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a texture resource +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CaptureTexture( + ID3D11Device* pDevice, + ID3D11DeviceContext* pContext, + ID3D11Resource* pSource, + ScratchImage& result) +{ + if (!pDevice || !pContext || !pSource) + return E_INVALIDARG; + + D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pSource->GetType(&resType); + + HRESULT hr; + + switch (resType) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + { + ComPtr pTexture; + hr = pSource->QueryInterface(IID_GRAPHICS_PPV_ARGS(pTexture.GetAddressOf())); + if (FAILED(hr)) + break; + + assert(pTexture); + + D3D11_TEXTURE1D_DESC desc; + pTexture->GetDesc(&desc); + + ComPtr pStaging; + if ((desc.Usage == D3D11_USAGE_STAGING) && (desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ)) + { + // Handle case where the source is already a staging texture we can use directly + pStaging = pTexture; + } + else + { + desc.BindFlags = 0; + desc.MiscFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + hr = pDevice->CreateTexture1D(&desc, 0, pStaging.GetAddressOf()); + if (FAILED(hr)) + break; + + assert(pStaging); + + pContext->CopyResource(pStaging.Get(), pSource); + } + + TexMetadata mdata; + mdata.width = desc.Width; + mdata.height = mdata.depth = 1; + mdata.arraySize = desc.ArraySize; + mdata.mipLevels = desc.MipLevels; + mdata.miscFlags = 0; + mdata.miscFlags2 = 0; + mdata.format = desc.Format; + mdata.dimension = TEX_DIMENSION_TEXTURE1D; + + hr = result.Initialize(mdata); + if (FAILED(hr)) + break; + + hr = Capture(pContext, pStaging.Get(), mdata, result); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + { + ComPtr pTexture; + hr = pSource->QueryInterface(IID_GRAPHICS_PPV_ARGS(pTexture.GetAddressOf())); + if (FAILED(hr)) + break; + + assert(pTexture); + + D3D11_TEXTURE2D_DESC desc; + pTexture->GetDesc(&desc); + + ComPtr pStaging; + if (desc.SampleDesc.Count > 1) + { + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + + ComPtr pTemp; + hr = pDevice->CreateTexture2D(&desc, 0, pTemp.GetAddressOf()); + if (FAILED(hr)) + break; + + assert(pTemp); + + DXGI_FORMAT fmt = desc.Format; + if (IsTypeless(fmt)) + { + // Assume a UNORM if it exists otherwise use FLOAT + fmt = MakeTypelessUNORM(fmt); + fmt = MakeTypelessFLOAT(fmt); + } + + UINT support = 0; + hr = pDevice->CheckFormatSupport(fmt, &support); + if (FAILED(hr)) + break; + + if (!(support & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE)) + { + hr = E_FAIL; + break; + } + + for (UINT item = 0; item < desc.ArraySize; ++item) + { + for (UINT level = 0; level < desc.MipLevels; ++level) + { + UINT index = D3D11CalcSubresource(level, item, desc.MipLevels); + pContext->ResolveSubresource(pTemp.Get(), index, pSource, index, fmt); + } + } + + desc.BindFlags = 0; + desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + hr = pDevice->CreateTexture2D(&desc, 0, pStaging.GetAddressOf()); + if (FAILED(hr)) + break; + + assert(pStaging); + + pContext->CopyResource(pStaging.Get(), pTemp.Get()); + } + else if ((desc.Usage == D3D11_USAGE_STAGING) && (desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ)) + { + // Handle case where the source is already a staging texture we can use directly + pStaging = pTexture; + } + else + { + desc.BindFlags = 0; + desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + hr = pDevice->CreateTexture2D(&desc, 0, &pStaging); + if (FAILED(hr)) + break; + + assert(pStaging); + + pContext->CopyResource(pStaging.Get(), pSource); + } + + TexMetadata mdata; + mdata.width = desc.Width; + mdata.height = desc.Height; + mdata.depth = 1; + mdata.arraySize = desc.ArraySize; + mdata.mipLevels = desc.MipLevels; + mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0; + mdata.miscFlags2 = 0; + mdata.format = desc.Format; + mdata.dimension = TEX_DIMENSION_TEXTURE2D; + + hr = result.Initialize(mdata); + if (FAILED(hr)) + break; + + hr = Capture(pContext, pStaging.Get(), mdata, result); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + { + ComPtr pTexture; + hr = pSource->QueryInterface(IID_GRAPHICS_PPV_ARGS(pTexture.GetAddressOf())); + if (FAILED(hr)) + break; + + assert(pTexture); + + D3D11_TEXTURE3D_DESC desc; + pTexture->GetDesc(&desc); + + ComPtr pStaging; + if ((desc.Usage == D3D11_USAGE_STAGING) && (desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ)) + { + // Handle case where the source is already a staging texture we can use directly + pStaging = pTexture; + } + else + { + desc.BindFlags = 0; + desc.MiscFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.Usage = D3D11_USAGE_STAGING; + + hr = pDevice->CreateTexture3D(&desc, 0, pStaging.GetAddressOf()); + if (FAILED(hr)) + break; + + assert(pStaging); + + pContext->CopyResource(pStaging.Get(), pSource); + } + + TexMetadata mdata; + mdata.width = desc.Width; + mdata.height = desc.Height; + mdata.depth = desc.Depth; + mdata.arraySize = 1; + mdata.mipLevels = desc.MipLevels; + mdata.miscFlags = 0; + mdata.miscFlags2 = 0; + mdata.format = desc.Format; + mdata.dimension = TEX_DIMENSION_TEXTURE3D; + + hr = result.Initialize(mdata); + if (FAILED(hr)) + break; + + hr = Capture(pContext, pStaging.Get(), mdata, result); + } + break; + + default: + hr = E_FAIL; + break; + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexDDS.cpp b/Kits/DirectXTex/DirectXTexDDS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f68568263fa40cd6e8065d2e02a07fffc539d18 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexDDS.cpp @@ -0,0 +1,2175 @@ +//------------------------------------------------------------------------------------- +// DirectXTexDDS.cpp +// +// DirectX Texture Library - Microsoft DirectDraw Surface (DDS) file format reader/writer +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "dds.h" + +using namespace DirectX; + +static_assert(static_cast(TEX_DIMENSION_TEXTURE1D) == static_cast(DDS_DIMENSION_TEXTURE1D), "header enum mismatch"); +static_assert(static_cast(TEX_DIMENSION_TEXTURE2D) == static_cast(DDS_DIMENSION_TEXTURE2D), "header enum mismatch"); +static_assert(static_cast(TEX_DIMENSION_TEXTURE3D) == static_cast(DDS_DIMENSION_TEXTURE3D), "header enum mismatch"); + +namespace +{ + //------------------------------------------------------------------------------------- + // Legacy format mapping table (used for DDS files without 'DX10' extended header) + //------------------------------------------------------------------------------------- + enum CONVERSION_FLAGS + { + CONV_FLAGS_NONE = 0x0, + CONV_FLAGS_EXPAND = 0x1, // Conversion requires expanded pixel size + CONV_FLAGS_NOALPHA = 0x2, // Conversion requires setting alpha to known value + CONV_FLAGS_SWIZZLE = 0x4, // BGR/RGB order swizzling required + CONV_FLAGS_PAL8 = 0x8, // Has an 8-bit palette + CONV_FLAGS_888 = 0x10, // Source is an 8:8:8 (24bpp) format + CONV_FLAGS_565 = 0x20, // Source is a 5:6:5 (16bpp) format + CONV_FLAGS_5551 = 0x40, // Source is a 5:5:5:1 (16bpp) format + CONV_FLAGS_4444 = 0x80, // Source is a 4:4:4:4 (16bpp) format + CONV_FLAGS_44 = 0x100, // Source is a 4:4 (8bpp) format + CONV_FLAGS_332 = 0x200, // Source is a 3:3:2 (8bpp) format + CONV_FLAGS_8332 = 0x400, // Source is a 8:3:3:2 (16bpp) format + CONV_FLAGS_A8P8 = 0x800, // Has an 8-bit palette with an alpha channel + CONV_FLAGS_DX10 = 0x10000, // Has the 'DX10' extension header + CONV_FLAGS_PMALPHA = 0x20000, // Contains premultiplied alpha data + CONV_FLAGS_L8 = 0x40000, // Source is a 8 luminance format + CONV_FLAGS_L16 = 0x80000, // Source is a 16 luminance format + CONV_FLAGS_A8L8 = 0x100000, // Source is a 8:8 luminance format + }; + + struct LegacyDDS + { + DXGI_FORMAT format; + DWORD convFlags; + DDS_PIXELFORMAT ddpf; + }; + + const LegacyDDS g_LegacyDDSMap[] = + { + { DXGI_FORMAT_BC1_UNORM, CONV_FLAGS_NONE, DDSPF_DXT1 }, // D3DFMT_DXT1 + { DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_NONE, DDSPF_DXT3 }, // D3DFMT_DXT3 + { DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, DDSPF_DXT5 }, // D3DFMT_DXT5 + + { DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT2 }, // D3DFMT_DXT2 + { DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT4 }, // D3DFMT_DXT4 + + { DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, DDSPF_BC4_UNORM }, + { DXGI_FORMAT_BC4_SNORM, CONV_FLAGS_NONE, DDSPF_BC4_SNORM }, + { DXGI_FORMAT_BC5_UNORM, CONV_FLAGS_NONE, DDSPF_BC5_UNORM }, + { DXGI_FORMAT_BC5_SNORM, CONV_FLAGS_NONE, DDSPF_BC5_SNORM }, + + { DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 } }, + { DXGI_FORMAT_BC5_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 } }, + + { DXGI_FORMAT_R8G8_B8G8_UNORM, CONV_FLAGS_NONE, DDSPF_R8G8_B8G8 }, // D3DFMT_R8G8_B8G8 + { DXGI_FORMAT_G8R8_G8B8_UNORM, CONV_FLAGS_NONE, DDSPF_G8R8_G8B8 }, // D3DFMT_G8R8_G8B8 + + { DXGI_FORMAT_B8G8R8A8_UNORM, CONV_FLAGS_NONE, DDSPF_A8R8G8B8 }, // D3DFMT_A8R8G8B8 (uses DXGI 1.1 format) + { DXGI_FORMAT_B8G8R8X8_UNORM, CONV_FLAGS_NONE, DDSPF_X8R8G8B8 }, // D3DFMT_X8R8G8B8 (uses DXGI 1.1 format) + { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_NONE, DDSPF_A8B8G8R8 }, // D3DFMT_A8B8G8R8 + { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_NOALPHA, DDSPF_X8B8G8R8 }, // D3DFMT_X8B8G8R8 + { DXGI_FORMAT_R16G16_UNORM, CONV_FLAGS_NONE, DDSPF_G16R16 }, // D3DFMT_G16R16 + + { DXGI_FORMAT_R10G10B10A2_UNORM, CONV_FLAGS_SWIZZLE, { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 } }, // D3DFMT_A2R10G10B10 (D3DX reversal issue workaround) + { DXGI_FORMAT_R10G10B10A2_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 } }, // D3DFMT_A2B10G10R10 (D3DX reversal issue workaround) + + { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND + | CONV_FLAGS_NOALPHA + | CONV_FLAGS_888, DDSPF_R8G8B8 }, // D3DFMT_R8G8B8 + + { DXGI_FORMAT_B5G6R5_UNORM, CONV_FLAGS_565, DDSPF_R5G6B5 }, // D3DFMT_R5G6B5 + { DXGI_FORMAT_B5G5R5A1_UNORM, CONV_FLAGS_5551, DDSPF_A1R5G5B5 }, // D3DFMT_A1R5G5B5 + { DXGI_FORMAT_B5G5R5A1_UNORM, CONV_FLAGS_5551 + | CONV_FLAGS_NOALPHA, { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x0000 } }, // D3DFMT_X1R5G5B5 + + { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND + | CONV_FLAGS_8332, { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00 } }, // D3DFMT_A8R3G3B2 + { DXGI_FORMAT_B5G6R5_UNORM, CONV_FLAGS_EXPAND + | CONV_FLAGS_332, { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0x00 } }, // D3DFMT_R3G3B2 + + { DXGI_FORMAT_R8_UNORM, CONV_FLAGS_NONE, DDSPF_L8 }, // D3DFMT_L8 + { DXGI_FORMAT_R16_UNORM, CONV_FLAGS_NONE, DDSPF_L16 }, // D3DFMT_L16 + { DXGI_FORMAT_R8G8_UNORM, CONV_FLAGS_NONE, DDSPF_A8L8 }, // D3DFMT_A8L8 + { DXGI_FORMAT_R8G8_UNORM, CONV_FLAGS_NONE, DDSPF_A8L8_ALT }, // D3DFMT_A8L8 (alternative bitcount) + + { DXGI_FORMAT_A8_UNORM, CONV_FLAGS_NONE, DDSPF_A8 }, // D3DFMT_A8 + + { DXGI_FORMAT_R16G16B16A16_UNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 36, 0, 0, 0, 0, 0 } }, // D3DFMT_A16B16G16R16 + { DXGI_FORMAT_R16G16B16A16_SNORM, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 110, 0, 0, 0, 0, 0 } }, // D3DFMT_Q16W16V16U16 + { DXGI_FORMAT_R16_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 111, 0, 0, 0, 0, 0 } }, // D3DFMT_R16F + { DXGI_FORMAT_R16G16_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 112, 0, 0, 0, 0, 0 } }, // D3DFMT_G16R16F + { DXGI_FORMAT_R16G16B16A16_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 113, 0, 0, 0, 0, 0 } }, // D3DFMT_A16B16G16R16F + { DXGI_FORMAT_R32_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 114, 0, 0, 0, 0, 0 } }, // D3DFMT_R32F + { DXGI_FORMAT_R32G32_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 115, 0, 0, 0, 0, 0 } }, // D3DFMT_G32R32F + { DXGI_FORMAT_R32G32B32A32_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, 116, 0, 0, 0, 0, 0 } }, // D3DFMT_A32B32G32R32F + + { DXGI_FORMAT_R32_FLOAT, CONV_FLAGS_NONE, { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0xffffffff, 0x00000000, 0x00000000, 0x00000000 } }, // D3DFMT_R32F (D3DX uses FourCC 114 instead) + + { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND + | CONV_FLAGS_PAL8 + | CONV_FLAGS_A8P8, { sizeof(DDS_PIXELFORMAT), DDS_PAL8A, 0, 16, 0, 0, 0, 0 } }, // D3DFMT_A8P8 + { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND + | CONV_FLAGS_PAL8, { sizeof(DDS_PIXELFORMAT), DDS_PAL8, 0, 8, 0, 0, 0, 0 } }, // D3DFMT_P8 + + { DXGI_FORMAT_B4G4R4A4_UNORM, CONV_FLAGS_4444, DDSPF_A4R4G4B4 }, // D3DFMT_A4R4G4B4 (uses DXGI 1.2 format) + { DXGI_FORMAT_B4G4R4A4_UNORM, CONV_FLAGS_NOALPHA + | CONV_FLAGS_4444, { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0f00, 0x00f0, 0x000f, 0x0000 } }, // D3DFMT_X4R4G4B4 (uses DXGI 1.2 format) + { DXGI_FORMAT_B4G4R4A4_UNORM, CONV_FLAGS_EXPAND + | CONV_FLAGS_44, { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA,0, 8, 0x0f, 0x00, 0x00, 0xf0 } }, // D3DFMT_A4L4 (uses DXGI 1.2 format) + + { DXGI_FORMAT_YUY2, CONV_FLAGS_NONE, DDSPF_YUY2 }, // D3DFMT_YUY2 (uses DXGI 1.2 format) + { DXGI_FORMAT_YUY2, CONV_FLAGS_SWIZZLE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('U','Y','V','Y'), 0, 0, 0, 0, 0 } }, // D3DFMT_UYVY (uses DXGI 1.2 format) + + { DXGI_FORMAT_R8G8_SNORM, CONV_FLAGS_NONE, DDSPF_V8U8 }, // D3DFMT_V8U8 + { DXGI_FORMAT_R8G8B8A8_SNORM, CONV_FLAGS_NONE, DDSPF_Q8W8V8U8 }, // D3DFMT_Q8W8V8U8 + { DXGI_FORMAT_R16G16_SNORM, CONV_FLAGS_NONE, DDSPF_V16U16 }, // D3DFMT_V16U16 + }; + + // 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 + + // We do not support the following legacy Direct3D 9 formats: + // BumpDuDv D3DFMT_A2W10V10U10 + // BumpLuminance D3DFMT_L6V5U5, D3DFMT_X8L8V8U8 + // FourCC 117 D3DFMT_CxV8U8 + // ZBuffer D3DFMT_D16_LOCKABLE + // FourCC 82 D3DFMT_D32F_LOCKABLE + + // We do not support the following known FourCC codes: + // FourCC CTX1 (Xbox 360 only) + // FourCC EAR, EARG, ET2, ET2A (Ericsson Texture Compression) + + DXGI_FORMAT GetDXGIFormat(const DDS_HEADER& hdr, const DDS_PIXELFORMAT& ddpf, DWORD flags, _Inout_ DWORD& convFlags) + { + uint32_t ddpfFlags = ddpf.dwFlags; + if (hdr.dwReserved1[9] == MAKEFOURCC('N', 'V', 'T', 'T')) + { + // Clear out non-standard nVidia DDS flags + ddpfFlags &= ~0xC0000000 /* DDPF_SRGB | DDPF_NORMAL */; + } + + const size_t MAP_SIZE = sizeof(g_LegacyDDSMap) / sizeof(LegacyDDS); + size_t index = 0; + for (index = 0; index < MAP_SIZE; ++index) + { + const LegacyDDS* entry = &g_LegacyDDSMap[index]; + + if (ddpfFlags == entry->ddpf.dwFlags) + { + if (entry->ddpf.dwFlags & DDS_FOURCC) + { + if (ddpf.dwFourCC == entry->ddpf.dwFourCC) + break; + } + else if (entry->ddpf.dwFlags & DDS_PAL8) + { + if (ddpf.dwRGBBitCount == entry->ddpf.dwRGBBitCount) + break; + } + else if (entry->ddpf.dwFlags & DDS_ALPHA) + { + if (ddpf.dwRGBBitCount == entry->ddpf.dwRGBBitCount + && ddpf.dwABitMask == entry->ddpf.dwABitMask) + break; + } + else if (entry->ddpf.dwFlags & DDS_LUMINANCE) + { + if (entry->ddpf.dwFlags & 0x1 /*DDPF_ALPHAPIXELS*/) + { + // LUMINANCEA + if (ddpf.dwRGBBitCount == entry->ddpf.dwRGBBitCount + && ddpf.dwRBitMask == entry->ddpf.dwRBitMask + && ddpf.dwABitMask == entry->ddpf.dwABitMask) + break; + } + else + { + // LUMINANCE + if (ddpf.dwRGBBitCount == entry->ddpf.dwRGBBitCount + && ddpf.dwRBitMask == entry->ddpf.dwRBitMask) + break; + } + } + else if (entry->ddpf.dwFlags & DDS_BUMPDUDV) + { + if (ddpf.dwRGBBitCount == entry->ddpf.dwRGBBitCount + && ddpf.dwRBitMask == entry->ddpf.dwRBitMask + && ddpf.dwGBitMask == entry->ddpf.dwGBitMask + && ddpf.dwBBitMask == entry->ddpf.dwBBitMask + && ddpf.dwABitMask == entry->ddpf.dwABitMask) + break; + } + else if (ddpf.dwRGBBitCount == entry->ddpf.dwRGBBitCount) + { + if (entry->ddpf.dwFlags & 0x1 /*DDPF_ALPHAPIXELS*/) + { + // RGBA + if (ddpf.dwRBitMask == entry->ddpf.dwRBitMask + && ddpf.dwGBitMask == entry->ddpf.dwGBitMask + && ddpf.dwBBitMask == entry->ddpf.dwBBitMask + && ddpf.dwABitMask == entry->ddpf.dwABitMask) + break; + } + else + { + // RGB + if (ddpf.dwRBitMask == entry->ddpf.dwRBitMask + && ddpf.dwGBitMask == entry->ddpf.dwGBitMask + && ddpf.dwBBitMask == entry->ddpf.dwBBitMask) + break; + } + } + } + } + + if (index >= MAP_SIZE) + return DXGI_FORMAT_UNKNOWN; + + DWORD cflags = g_LegacyDDSMap[index].convFlags; + DXGI_FORMAT format = g_LegacyDDSMap[index].format; + + if ((cflags & CONV_FLAGS_EXPAND) && (flags & DDS_FLAGS_NO_LEGACY_EXPANSION)) + return DXGI_FORMAT_UNKNOWN; + + if ((format == DXGI_FORMAT_R10G10B10A2_UNORM) && (flags & DDS_FLAGS_NO_R10B10G10A2_FIXUP)) + { + cflags ^= CONV_FLAGS_SWIZZLE; + } + + if ((hdr.dwReserved1[9] == MAKEFOURCC('N', 'V', 'T', 'T')) + && (ddpf.dwFlags & 0x40000000 /* DDPF_SRGB */)) + { + format = MakeSRGB(format); + } + + convFlags = cflags; + + return format; + } + + + //------------------------------------------------------------------------------------- + // Decodes DDS header including optional DX10 extended header + //------------------------------------------------------------------------------------- + HRESULT DecodeDDSHeader( + _In_reads_bytes_(size) const void* pSource, + size_t size, + DWORD flags, + _Out_ TexMetadata& metadata, + _Inout_ DWORD& convFlags) + { + if (!pSource) + return E_INVALIDARG; + + memset(&metadata, 0, sizeof(TexMetadata)); + + if (size < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + // DDS files always start with the same magic number ("DDS ") + uint32_t dwMagicNumber = *reinterpret_cast(pSource); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto pHeader = reinterpret_cast((const uint8_t*)pSource + sizeof(uint32_t)); + + // Verify header to validate DDS file + if (pHeader->dwSize != sizeof(DDS_HEADER) + || pHeader->ddspf.dwSize != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + metadata.mipLevels = pHeader->dwMipMapCount; + if (metadata.mipLevels == 0) + metadata.mipLevels = 1; + + // Check for DX10 extension + if ((pHeader->ddspf.dwFlags & DDS_FOURCC) + && (MAKEFOURCC('D', 'X', '1', '0') == pHeader->ddspf.dwFourCC)) + { + // Buffer must be big enough for both headers and magic value + if (size < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) + { + return E_FAIL; + } + + auto d3d10ext = reinterpret_cast((const uint8_t*)pSource + sizeof(uint32_t) + sizeof(DDS_HEADER)); + convFlags |= CONV_FLAGS_DX10; + + metadata.arraySize = d3d10ext->arraySize; + if (metadata.arraySize == 0) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + metadata.format = d3d10ext->dxgiFormat; + if (!IsValid(metadata.format) || IsPalettized(metadata.format)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + static_assert(static_cast(TEX_MISC_TEXTURECUBE) == static_cast(DDS_RESOURCE_MISC_TEXTURECUBE), "DDS header mismatch"); + + metadata.miscFlags = d3d10ext->miscFlag & ~TEX_MISC_TEXTURECUBE; + + switch (d3d10ext->resourceDimension) + { + case DDS_DIMENSION_TEXTURE1D: + + // D3DX writes 1D textures with a fixed Height of 1 + if ((pHeader->dwFlags & DDS_HEIGHT) && pHeader->dwHeight != 1) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + metadata.width = pHeader->dwWidth; + metadata.height = 1; + metadata.depth = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE1D; + break; + + case DDS_DIMENSION_TEXTURE2D: + if (d3d10ext->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) + { + metadata.miscFlags |= TEX_MISC_TEXTURECUBE; + metadata.arraySize *= 6; + } + + metadata.width = pHeader->dwWidth; + metadata.height = pHeader->dwHeight; + metadata.depth = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + break; + + case DDS_DIMENSION_TEXTURE3D: + if (!(pHeader->dwFlags & DDS_HEADER_FLAGS_VOLUME)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + if (metadata.arraySize > 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + metadata.width = pHeader->dwWidth; + metadata.height = pHeader->dwHeight; + metadata.depth = pHeader->dwDepth; + metadata.dimension = TEX_DIMENSION_TEXTURE3D; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + static_assert(static_cast(TEX_MISC2_ALPHA_MODE_MASK) == static_cast(DDS_MISC_FLAGS2_ALPHA_MODE_MASK), "DDS header mismatch"); + + static_assert(static_cast(TEX_ALPHA_MODE_UNKNOWN) == static_cast(DDS_ALPHA_MODE_UNKNOWN), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_STRAIGHT) == static_cast(DDS_ALPHA_MODE_STRAIGHT), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_PREMULTIPLIED) == static_cast(DDS_ALPHA_MODE_PREMULTIPLIED), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_OPAQUE) == static_cast(DDS_ALPHA_MODE_OPAQUE), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_CUSTOM) == static_cast(DDS_ALPHA_MODE_CUSTOM), "DDS header mismatch"); + + metadata.miscFlags2 = d3d10ext->miscFlags2; + } + else + { + metadata.arraySize = 1; + + if (pHeader->dwFlags & DDS_HEADER_FLAGS_VOLUME) + { + metadata.width = pHeader->dwWidth; + metadata.height = pHeader->dwHeight; + metadata.depth = pHeader->dwDepth; + metadata.dimension = TEX_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); + + metadata.arraySize = 6; + metadata.miscFlags |= TEX_MISC_TEXTURECUBE; + } + + metadata.width = pHeader->dwWidth; + metadata.height = pHeader->dwHeight; + metadata.depth = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + + // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture + } + + metadata.format = GetDXGIFormat(*pHeader, pHeader->ddspf, flags, convFlags); + + if (metadata.format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (convFlags & CONV_FLAGS_PMALPHA) + metadata.miscFlags2 |= TEX_ALPHA_MODE_PREMULTIPLIED; + + // Special flag for handling LUMINANCE legacy formats + if (flags & DDS_FLAGS_EXPAND_LUMINANCE) + { + switch (metadata.format) + { + case DXGI_FORMAT_R8_UNORM: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + convFlags |= CONV_FLAGS_L8 | CONV_FLAGS_EXPAND; + break; + + case DXGI_FORMAT_R8G8_UNORM: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + convFlags |= CONV_FLAGS_A8L8 | CONV_FLAGS_EXPAND; + break; + + case DXGI_FORMAT_R16_UNORM: + metadata.format = DXGI_FORMAT_R16G16B16A16_UNORM; + convFlags |= CONV_FLAGS_L16 | CONV_FLAGS_EXPAND; + break; + + default: + break; + } + } + } + + // Special flag for handling BGR DXGI 1.1 formats + if (flags & DDS_FLAGS_FORCE_RGB) + { + switch (metadata.format) + { + case DXGI_FORMAT_B8G8R8A8_UNORM: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + convFlags |= CONV_FLAGS_SWIZZLE; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA; + break; + + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS; + convFlags |= CONV_FLAGS_SWIZZLE; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + convFlags |= CONV_FLAGS_SWIZZLE; + break; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS; + convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA; + break; + + default: + break; + } + } + + // Special flag for handling 16bpp formats + if (flags & DDS_FLAGS_NO_16BPP) + { + switch (metadata.format) + { + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + convFlags |= CONV_FLAGS_EXPAND; + if (metadata.format == DXGI_FORMAT_B5G6R5_UNORM) + convFlags |= CONV_FLAGS_NOALPHA; + + default: + break; + } + } + + return S_OK; + } +} + + +//------------------------------------------------------------------------------------- +// Encodes DDS file header (magic value, header, optional DX10 extended header) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::_EncodeDDSHeader( + const TexMetadata& metadata, + DWORD flags, + void* pDestination, + size_t maxsize, + size_t& required) +{ + if (!IsValid(metadata.format)) + return E_INVALIDARG; + + if (IsPalettized(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (metadata.arraySize > 1) + { + if ((metadata.arraySize != 6) || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) || !(metadata.IsCubemap())) + { + // Texture1D arrays, Texture2D arrays, and Cubemap arrays must be stored using 'DX10' extended header + flags |= DDS_FLAGS_FORCE_DX10_EXT; + } + } + + if (flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2) + { + flags |= DDS_FLAGS_FORCE_DX10_EXT; + } + + DDS_PIXELFORMAT ddpf = { 0 }; + if (!(flags & DDS_FLAGS_FORCE_DX10_EXT)) + { + switch (metadata.format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_A8B8G8R8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R16G16_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_G16R16, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R8G8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_A8L8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R16_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_L16, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_L8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_A8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_A8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC1_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC2_UNORM: memcpy_s(&ddpf, sizeof(ddpf), metadata.IsPMAlpha() ? (&DDSPF_DXT2) : (&DDSPF_DXT3), sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC3_UNORM: memcpy_s(&ddpf, sizeof(ddpf), metadata.IsPMAlpha() ? (&DDSPF_DXT4) : (&DDSPF_DXT5), sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC4_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC4_SNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC5_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_BC5_SNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_BC5_SNORM, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_B5G6R5_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_R5G6B5, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_B5G5R5A1_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_A1R5G5B5, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R8G8_SNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_V8U8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R8G8B8A8_SNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_Q8W8V8U8, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_R16G16_SNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_V16U16, sizeof(DDS_PIXELFORMAT)); break; + case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_A8R8G8B8, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.1 + case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.1 + case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2 + case DXGI_FORMAT_YUY2: memcpy_s(&ddpf, sizeof(ddpf), &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2 + + // Legacy D3DX formats using D3DFMT enum value as FourCC + case DXGI_FORMAT_R32G32B32A32_FLOAT: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 116; // D3DFMT_A32B32G32R32F + break; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 113; // D3DFMT_A16B16G16R16F + break; + case DXGI_FORMAT_R16G16B16A16_UNORM: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 36; // D3DFMT_A16B16G16R16 + break; + case DXGI_FORMAT_R16G16B16A16_SNORM: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 110; // D3DFMT_Q16W16V16U16 + break; + case DXGI_FORMAT_R32G32_FLOAT: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 115; // D3DFMT_G32R32F + break; + case DXGI_FORMAT_R16G16_FLOAT: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 112; // D3DFMT_G16R16F + break; + case DXGI_FORMAT_R32_FLOAT: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 114; // D3DFMT_R32F + break; + case DXGI_FORMAT_R16_FLOAT: + ddpf.dwSize = sizeof(DDS_PIXELFORMAT); ddpf.dwFlags = DDS_FOURCC; ddpf.dwFourCC = 111; // D3DFMT_R16F + break; + + default: + break; + } + } + + required = sizeof(uint32_t) + sizeof(DDS_HEADER); + + if (ddpf.dwSize == 0) + required += sizeof(DDS_HEADER_DXT10); + + if (!pDestination) + return S_OK; + + if (maxsize < required) + return E_NOT_SUFFICIENT_BUFFER; + + *reinterpret_cast(pDestination) = DDS_MAGIC; + + auto header = reinterpret_cast(reinterpret_cast(pDestination) + sizeof(uint32_t)); + assert(header); + + memset(header, 0, sizeof(DDS_HEADER)); + header->dwSize = sizeof(DDS_HEADER); + header->dwFlags = DDS_HEADER_FLAGS_TEXTURE; + header->dwCaps = DDS_SURFACE_FLAGS_TEXTURE; + + if (metadata.mipLevels > 0) + { + header->dwFlags |= DDS_HEADER_FLAGS_MIPMAP; + + if (metadata.mipLevels > UINT16_MAX) + return E_INVALIDARG; + + header->dwMipMapCount = static_cast(metadata.mipLevels); + + if (header->dwMipMapCount > 1) + header->dwCaps |= DDS_SURFACE_FLAGS_MIPMAP; + } + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (metadata.width > UINT32_MAX) + return E_INVALIDARG; + + header->dwWidth = static_cast(metadata.width); + header->dwHeight = header->dwDepth = 1; + break; + + case TEX_DIMENSION_TEXTURE2D: + if (metadata.height > UINT32_MAX + || metadata.width > UINT32_MAX) + return E_INVALIDARG; + + header->dwHeight = static_cast(metadata.height); + header->dwWidth = static_cast(metadata.width); + header->dwDepth = 1; + + if (metadata.IsCubemap()) + { + header->dwCaps |= DDS_SURFACE_FLAGS_CUBEMAP; + header->dwCaps2 |= DDS_CUBEMAP_ALLFACES; + } + break; + + case TEX_DIMENSION_TEXTURE3D: + if (metadata.height > UINT32_MAX + || metadata.width > UINT32_MAX + || metadata.depth > UINT16_MAX) + return E_INVALIDARG; + + header->dwFlags |= DDS_HEADER_FLAGS_VOLUME; + header->dwCaps2 |= DDS_FLAGS_VOLUME; + header->dwHeight = static_cast(metadata.height); + header->dwWidth = static_cast(metadata.width); + header->dwDepth = static_cast(metadata.depth); + break; + + default: + return E_FAIL; + } + + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE); + + if (slicePitch > UINT32_MAX + || rowPitch > UINT32_MAX) + return E_FAIL; + + if (IsCompressed(metadata.format)) + { + header->dwFlags |= DDS_HEADER_FLAGS_LINEARSIZE; + header->dwPitchOrLinearSize = static_cast(slicePitch); + } + else + { + header->dwFlags |= DDS_HEADER_FLAGS_PITCH; + header->dwPitchOrLinearSize = static_cast(rowPitch); + } + + if (ddpf.dwSize == 0) + { + memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT)); + + auto ext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + assert(ext); + + memset(ext, 0, sizeof(DDS_HEADER_DXT10)); + ext->dxgiFormat = metadata.format; + ext->resourceDimension = metadata.dimension; + + if (metadata.arraySize > UINT16_MAX) + return E_INVALIDARG; + + static_assert(static_cast(TEX_MISC_TEXTURECUBE) == static_cast(DDS_RESOURCE_MISC_TEXTURECUBE), "DDS header mismatch"); + + ext->miscFlag = metadata.miscFlags & ~TEX_MISC_TEXTURECUBE; + + if (metadata.miscFlags & TEX_MISC_TEXTURECUBE) + { + ext->miscFlag |= TEX_MISC_TEXTURECUBE; + assert((metadata.arraySize % 6) == 0); + ext->arraySize = static_cast(metadata.arraySize / 6); + } + else + { + ext->arraySize = static_cast(metadata.arraySize); + } + + static_assert(static_cast(TEX_MISC2_ALPHA_MODE_MASK) == static_cast(DDS_MISC_FLAGS2_ALPHA_MODE_MASK), "DDS header mismatch"); + + static_assert(static_cast(TEX_ALPHA_MODE_UNKNOWN) == static_cast(DDS_ALPHA_MODE_UNKNOWN), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_STRAIGHT) == static_cast(DDS_ALPHA_MODE_STRAIGHT), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_PREMULTIPLIED) == static_cast(DDS_ALPHA_MODE_PREMULTIPLIED), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_OPAQUE) == static_cast(DDS_ALPHA_MODE_OPAQUE), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_CUSTOM) == static_cast(DDS_ALPHA_MODE_CUSTOM), "DDS header mismatch"); + + if (flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2) + { + // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0 + ext->miscFlags2 = metadata.miscFlags2; + } + } + else + { + memcpy_s(&header->ddspf, sizeof(header->ddspf), &ddpf, sizeof(ddpf)); + } + + return S_OK; +} + + +namespace +{ + //------------------------------------------------------------------------------------- + // Converts an image row with optional clearing of alpha value to 1.0 + // Returns true if supported, false if expansion case not supported + //------------------------------------------------------------------------------------- + enum TEXP_LEGACY_FORMAT + { + TEXP_LEGACY_UNKNOWN = 0, + TEXP_LEGACY_R8G8B8, + TEXP_LEGACY_R3G3B2, + TEXP_LEGACY_A8R3G3B2, + TEXP_LEGACY_P8, + TEXP_LEGACY_A8P8, + TEXP_LEGACY_A4L4, + TEXP_LEGACY_B4G4R4A4, + TEXP_LEGACY_L8, + TEXP_LEGACY_L16, + TEXP_LEGACY_A8L8 + }; + + inline TEXP_LEGACY_FORMAT _FindLegacyFormat(DWORD flags) + { + TEXP_LEGACY_FORMAT lformat = TEXP_LEGACY_UNKNOWN; + + if (flags & CONV_FLAGS_PAL8) + { + lformat = (flags & CONV_FLAGS_A8P8) ? TEXP_LEGACY_A8P8 : TEXP_LEGACY_P8; + } + else if (flags & CONV_FLAGS_888) + lformat = TEXP_LEGACY_R8G8B8; + else if (flags & CONV_FLAGS_332) + lformat = TEXP_LEGACY_R3G3B2; + else if (flags & CONV_FLAGS_8332) + lformat = TEXP_LEGACY_A8R3G3B2; + else if (flags & CONV_FLAGS_44) + lformat = TEXP_LEGACY_A4L4; + else if (flags & CONV_FLAGS_4444) + lformat = TEXP_LEGACY_B4G4R4A4; + else if (flags & CONV_FLAGS_L8) + lformat = TEXP_LEGACY_L8; + else if (flags & CONV_FLAGS_L16) + lformat = TEXP_LEGACY_L16; + else if (flags & CONV_FLAGS_A8L8) + lformat = TEXP_LEGACY_A8L8; + + return lformat; + } + + _Success_(return != false) + bool LegacyExpandScanline( + _Out_writes_bytes_(outSize) void* pDestination, + size_t outSize, + _In_ DXGI_FORMAT outFormat, + _In_reads_bytes_(inSize) const void* pSource, + size_t inSize, + _In_ TEXP_LEGACY_FORMAT inFormat, + _In_reads_opt_(256) const uint32_t* pal8, + _In_ DWORD flags) + { + assert(pDestination && outSize > 0); + assert(pSource && inSize > 0); + assert(IsValid(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat)); + + switch (inFormat) + { + case TEXP_LEGACY_R8G8B8: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // D3DFMT_R8G8B8 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 3 && outSize >= 4) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 2)) && (ocount < (outSize - 3))); icount += 3, ocount += 4) + { + // 24bpp Direct3D 9 files are actually BGR, so need to swizzle as well + uint32_t t1 = (*(sPtr) << 16); + uint32_t t2 = (*(sPtr + 1) << 8); + uint32_t t3 = *(sPtr + 2); + + *(dPtr++) = t1 | t2 | t3 | 0xff000000; + sPtr += 3; + } + return true; + } + return false; + + case TEXP_LEGACY_R3G3B2: + switch (outFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + // D3DFMT_R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 1 && outSize >= 4) + { + const uint8_t* __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4) + { + uint8_t t = *(sPtr++); + + uint32_t t1 = (t & 0xe0) | ((t & 0xe0) >> 3) | ((t & 0xc0) >> 6); + uint32_t t2 = ((t & 0x1c) << 11) | ((t & 0x1c) << 8) | ((t & 0x18) << 5); + uint32_t t3 = ((t & 0x03) << 22) | ((t & 0x03) << 20) | ((t & 0x03) << 18) | ((t & 0x03) << 16); + + *(dPtr++) = t1 | t2 | t3 | 0xff000000; + } + return true; + } + return false; + + case DXGI_FORMAT_B5G6R5_UNORM: + // D3DFMT_R3G3B2 -> DXGI_FORMAT_B5G6R5_UNORM + if (inSize >= 1 && outSize >= 2) + { + const uint8_t* __restrict sPtr = reinterpret_cast(pSource); + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2) + { + uint8_t t = *(sPtr++); + + uint16_t t1 = ((t & 0xe0) << 8) | ((t & 0xc0) << 5); + uint16_t t2 = ((t & 0x1c) << 6) | ((t & 0x1c) << 3); + uint16_t t3 = ((t & 0x03) << 3) | ((t & 0x03) << 1) | ((t & 0x02) >> 1); + + *(dPtr++) = t1 | t2 | t3; + } + return true; + } + return false; + + default: + return false; + } + break; + + case TEXP_LEGACY_A8R3G3B2: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // D3DFMT_A8R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t* __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = (t & 0x00e0) | ((t & 0x00e0) >> 3) | ((t & 0x00c0) >> 6); + uint32_t t2 = ((t & 0x001c) << 11) | ((t & 0x001c) << 8) | ((t & 0x0018) << 5); + uint32_t t3 = ((t & 0x0003) << 22) | ((t & 0x0003) << 20) | ((t & 0x0003) << 18) | ((t & 0x0003) << 16); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : ((t & 0xff00) << 16); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + return true; + } + return false; + + case TEXP_LEGACY_P8: + if ((outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8) + return false; + + // D3DFMT_P8 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 1 && outSize >= 4) + { + const uint8_t* __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4) + { + uint8_t t = *(sPtr++); + + *(dPtr++) = pal8[t]; + } + return true; + } + return false; + + case TEXP_LEGACY_A8P8: + if ((outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8) + return false; + + // D3DFMT_A8P8 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t* __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = pal8[t & 0xff]; + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : ((t & 0xff00) << 16); + + *(dPtr++) = t1 | ta; + } + return true; + } + return false; + + case TEXP_LEGACY_A4L4: + switch (outFormat) + { + case DXGI_FORMAT_B4G4R4A4_UNORM: + // D3DFMT_A4L4 -> DXGI_FORMAT_B4G4R4A4_UNORM + if (inSize >= 1 && outSize >= 2) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + uint16_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2) + { + uint8_t t = *(sPtr++); + + uint16_t t1 = (t & 0x0f); + uint16_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xf000 : ((t & 0xf0) << 8); + + *(dPtr++) = t1 | (t1 << 4) | (t1 << 8) | ta; + } + return true; + } + return false; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + // D3DFMT_A4L4 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 1 && outSize >= 4) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4) + { + uint8_t t = *(sPtr++); + + uint32_t t1 = ((t & 0x0f) << 4) | (t & 0x0f); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (((t & 0xf0) << 24) | ((t & 0xf0) << 20)); + + *(dPtr++) = t1 | (t1 << 8) | (t1 << 16) | ta; + } + return true; + } + return false; + + default: + return false; + } + break; + + case TEXP_LEGACY_B4G4R4A4: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // D3DFMT_A4R4G4B4 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = ((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8); + uint32_t t2 = ((t & 0x00f0) << 8) | ((t & 0x00f0) << 4); + uint32_t t3 = ((t & 0x000f) << 20) | ((t & 0x000f) << 16); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (((t & 0xf000) << 16) | ((t & 0xf000) << 12)); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + return true; + } + return false; + + case TEXP_LEGACY_L8: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // D3DFMT_L8 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 1 && outSize >= 4) + { + const uint8_t * __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4) + { + uint32_t t1 = *(sPtr++); + uint32_t t2 = (t1 << 8); + uint32_t t3 = (t1 << 16); + + *(dPtr++) = t1 | t2 | t3 | 0xff000000; + } + return true; + } + return false; + + case TEXP_LEGACY_L16: + if (outFormat != DXGI_FORMAT_R16G16B16A16_UNORM) + return false; + + // D3DFMT_L16 -> DXGI_FORMAT_R16G16B16A16_UNORM + if (inSize >= 2 && outSize >= 8) + { + const uint16_t* __restrict sPtr = reinterpret_cast(pSource); + uint64_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 7))); icount += 2, ocount += 8) + { + uint16_t t = *(sPtr++); + + uint64_t t1 = t; + uint64_t t2 = (t1 << 16); + uint64_t t3 = (t1 << 32); + + *(dPtr++) = t1 | t2 | t3 | 0xffff000000000000; + } + return true; + } + return false; + + case TEXP_LEGACY_A8L8: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // D3DFMT_A8L8 -> DXGI_FORMAT_R8G8B8A8_UNORM + if (inSize >= 2 && outSize >= 4) + { + const uint16_t* __restrict sPtr = reinterpret_cast(pSource); + uint32_t * __restrict dPtr = reinterpret_cast(pDestination); + + for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4) + { + uint16_t t = *(sPtr++); + + uint32_t t1 = (t & 0xff); + uint32_t t2 = (t1 << 8); + uint32_t t3 = (t1 << 16); + uint32_t ta = (flags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : ((t & 0xff00) << 16); + + *(dPtr++) = t1 | t2 | t3 | ta; + } + return true; + } + return false; + + default: + return false; + } + } + + + //------------------------------------------------------------------------------------- + // Converts or copies image data from pPixels into scratch image data + //------------------------------------------------------------------------------------- + HRESULT CopyImage( + _In_reads_bytes_(size) const void* pPixels, + _In_ size_t size, + _In_ const TexMetadata& metadata, + _In_ DWORD cpFlags, + _In_ DWORD convFlags, + _In_reads_opt_(256) const uint32_t *pal8, + _In_ const ScratchImage& image) + { + assert(pPixels); + assert(image.GetPixels()); + + if (!size) + return E_FAIL; + + if (convFlags & CONV_FLAGS_EXPAND) + { + if (convFlags & CONV_FLAGS_888) + cpFlags |= CP_FLAGS_24BPP; + else if (convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8)) + cpFlags |= CP_FLAGS_16BPP; + else if (convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8 | CONV_FLAGS_L8)) + cpFlags |= CP_FLAGS_8BPP; + } + + size_t pixelSize, nimages; + _DetermineImageArray(metadata, cpFlags, nimages, pixelSize); + if ((nimages == 0) || (nimages != image.GetImageCount())) + { + return E_FAIL; + } + + if (pixelSize > size) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + std::unique_ptr timages(new (std::nothrow) Image[nimages]); + if (!timages) + { + return E_OUTOFMEMORY; + } + + if (!_SetupImageArray((uint8_t*)pPixels, pixelSize, metadata, cpFlags, timages.get(), nimages)) + { + return E_FAIL; + } + + if (nimages != image.GetImageCount()) + { + return E_FAIL; + } + + const Image* images = image.GetImages(); + if (!images) + { + return E_FAIL; + } + + DWORD tflags = (convFlags & CONV_FLAGS_NOALPHA) ? TEXP_SCANLINE_SETALPHA : 0; + if (convFlags & CONV_FLAGS_SWIZZLE) + tflags |= TEXP_SCANLINE_LEGACY; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + { + size_t index = 0; + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t lastgood = 0; + for (size_t level = 0; level < metadata.mipLevels; ++level, ++index) + { + if (index >= nimages) + return E_FAIL; + + if (images[index].height != timages[index].height) + return E_FAIL; + + size_t dpitch = images[index].rowPitch; + size_t spitch = timages[index].rowPitch; + + const uint8_t *pSrc = const_cast(timages[index].pixels); + if (!pSrc) + return E_POINTER; + + uint8_t *pDest = images[index].pixels; + if (!pDest) + return E_POINTER; + + if (IsCompressed(metadata.format)) + { + size_t csize = std::min(images[index].slicePitch, timages[index].slicePitch); + memcpy_s(pDest, images[index].slicePitch, pSrc, csize); + + if (cpFlags & CP_FLAGS_BAD_DXTN_TAILS) + { + if (images[index].width < 4 || images[index].height < 4) + { + csize = std::min(images[index].slicePitch, timages[lastgood].slicePitch); + memcpy_s(pDest, images[index].slicePitch, timages[lastgood].pixels, csize); + } + else + { + lastgood = index; + } + } + } + else if (IsPlanar(metadata.format)) + { + size_t count = ComputeScanlines(metadata.format, images[index].height); + if (!count) + return E_UNEXPECTED; + + size_t csize = std::min(dpitch, spitch); + for (size_t h = 0; h < count; ++h) + { + memcpy_s(pDest, dpitch, pSrc, csize); + pSrc += spitch; + pDest += dpitch; + } + } + else + { + for (size_t h = 0; h < images[index].height; ++h) + { + if (convFlags & CONV_FLAGS_EXPAND) + { + if (convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444)) + { + if (!_ExpandScanline(pDest, dpitch, DXGI_FORMAT_R8G8B8A8_UNORM, + pSrc, spitch, + (convFlags & CONV_FLAGS_565) ? DXGI_FORMAT_B5G6R5_UNORM : DXGI_FORMAT_B5G5R5A1_UNORM, + tflags)) + return E_FAIL; + } + else + { + TEXP_LEGACY_FORMAT lformat = _FindLegacyFormat(convFlags); + if (!LegacyExpandScanline(pDest, dpitch, metadata.format, + pSrc, spitch, lformat, pal8, + tflags)) + return E_FAIL; + } + } + else if (convFlags & CONV_FLAGS_SWIZZLE) + { + _SwizzleScanline(pDest, dpitch, pSrc, spitch, + metadata.format, tflags); + } + else + { + _CopyScanline(pDest, dpitch, pSrc, spitch, + metadata.format, tflags); + } + + pSrc += spitch; + pDest += dpitch; + } + } + } + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + size_t index = 0; + size_t d = metadata.depth; + + size_t lastgood = 0; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + for (size_t slice = 0; slice < d; ++slice, ++index) + { + if (index >= nimages) + return E_FAIL; + + if (images[index].height != timages[index].height) + return E_FAIL; + + size_t dpitch = images[index].rowPitch; + size_t spitch = timages[index].rowPitch; + + const uint8_t *pSrc = const_cast(timages[index].pixels); + if (!pSrc) + return E_POINTER; + + uint8_t *pDest = images[index].pixels; + if (!pDest) + return E_POINTER; + + if (IsCompressed(metadata.format)) + { + size_t csize = std::min(images[index].slicePitch, timages[index].slicePitch); + memcpy_s(pDest, images[index].slicePitch, pSrc, csize); + + if (cpFlags & CP_FLAGS_BAD_DXTN_TAILS) + { + if (images[index].width < 4 || images[index].height < 4) + { + csize = std::min(images[index].slicePitch, timages[lastgood + slice].slicePitch); + memcpy_s(pDest, images[index].slicePitch, timages[lastgood + slice].pixels, csize); + } + else if (!slice) + { + lastgood = index; + } + } + } + else if (IsPlanar(metadata.format)) + { + // Direct3D does not support any planar formats for Texture3D + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + else + { + for (size_t h = 0; h < images[index].height; ++h) + { + if (convFlags & CONV_FLAGS_EXPAND) + { + if (convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444)) + { + if (!_ExpandScanline(pDest, dpitch, DXGI_FORMAT_R8G8B8A8_UNORM, + pSrc, spitch, + (convFlags & CONV_FLAGS_565) ? DXGI_FORMAT_B5G6R5_UNORM : DXGI_FORMAT_B5G5R5A1_UNORM, + tflags)) + return E_FAIL; + } + else + { + TEXP_LEGACY_FORMAT lformat = _FindLegacyFormat(convFlags); + if (!LegacyExpandScanline(pDest, dpitch, metadata.format, + pSrc, spitch, lformat, pal8, + tflags)) + return E_FAIL; + } + } + else if (convFlags & CONV_FLAGS_SWIZZLE) + { + _SwizzleScanline(pDest, dpitch, pSrc, spitch, metadata.format, tflags); + } + else + { + _CopyScanline(pDest, dpitch, pSrc, spitch, metadata.format, tflags); + } + + pSrc += spitch; + pDest += dpitch; + } + } + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + return E_FAIL; + } + + return S_OK; + } + + HRESULT CopyImageInPlace(DWORD convFlags, _In_ const ScratchImage& image) + { + if (!image.GetPixels()) + return E_FAIL; + + const Image* images = image.GetImages(); + if (!images) + return E_FAIL; + + const TexMetadata& metadata = image.GetMetadata(); + + if (IsPlanar(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + DWORD tflags = (convFlags & CONV_FLAGS_NOALPHA) ? TEXP_SCANLINE_SETALPHA : 0; + if (convFlags & CONV_FLAGS_SWIZZLE) + tflags |= TEXP_SCANLINE_LEGACY; + + for (size_t i = 0; i < image.GetImageCount(); ++i) + { + const Image* img = &images[i]; + uint8_t *pPixels = img->pixels; + if (!pPixels) + return E_POINTER; + + size_t rowPitch = img->rowPitch; + + for (size_t h = 0; h < img->height; ++h) + { + if (convFlags & CONV_FLAGS_SWIZZLE) + { + _SwizzleScanline(pPixels, rowPitch, pPixels, rowPitch, metadata.format, tflags); + } + else + { + _CopyScanline(pPixels, rowPitch, pPixels, rowPitch, metadata.format, tflags); + } + + pPixels += rowPitch; + } + } + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Obtain metadata from DDS file in memory/on disk +//------------------------------------------------------------------------------------- + +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromDDSMemory( + const void* pSource, + size_t size, + DWORD flags, + TexMetadata& metadata) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + DWORD convFlags = 0; + return DecodeDDSHeader(pSource, size, flags, metadata, convFlags); +} + +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromDDSFile( + const wchar_t* szFile, + DWORD flags, + TexMetadata& metadata) +{ + if (!szFile) + return E_INVALIDARG; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid DDS file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the standard header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // Read the header in (including extended header if present) + const size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); + uint8_t header[MAX_HEADER_SIZE]; + + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, MAX_HEADER_SIZE, &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + DWORD convFlags = 0; + return DecodeDDSHeader(header, bytesRead, flags, metadata, convFlags); +} + + +//------------------------------------------------------------------------------------- +// Load a DDS file in memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromDDSMemory( + const void* pSource, + size_t size, + DWORD flags, + TexMetadata* metadata, + ScratchImage& image) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + image.Release(); + + DWORD convFlags = 0; + TexMetadata mdata; + HRESULT hr = DecodeDDSHeader(pSource, size, flags, mdata, convFlags); + if (FAILED(hr)) + return hr; + + size_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER); + if (convFlags & CONV_FLAGS_DX10) + offset += sizeof(DDS_HEADER_DXT10); + + assert(offset <= size); + + const uint32_t *pal8 = nullptr; + if (convFlags & CONV_FLAGS_PAL8) + { + pal8 = reinterpret_cast(reinterpret_cast(pSource) + offset); + assert(pal8); + offset += (256 * sizeof(uint32_t)); + if (size < offset) + return E_FAIL; + } + + hr = image.Initialize(mdata); + if (FAILED(hr)) + return hr; + + DWORD cflags = CP_FLAGS_NONE; + if (flags & DDS_FLAGS_LEGACY_DWORD) + { + cflags |= CP_FLAGS_LEGACY_DWORD; + } + if (flags & DDS_FLAGS_BAD_DXTN_TAILS) + { + cflags |= CP_FLAGS_BAD_DXTN_TAILS; + } + + auto pPixels = reinterpret_cast(reinterpret_cast(pSource) + offset); + assert(pPixels); + hr = CopyImage(pPixels, + size - offset, + mdata, + cflags, + convFlags, + pal8, + image); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Load a DDS file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromDDSFile( + const wchar_t* szFile, + DWORD flags, + TexMetadata* metadata, + ScratchImage& image) +{ + if (!szFile) + return E_INVALIDARG; + + image.Release(); + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid DDS file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the standard header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // Read the header in (including extended header if present) + const size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); + uint8_t header[MAX_HEADER_SIZE]; + + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, MAX_HEADER_SIZE, &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + DWORD convFlags = 0; + TexMetadata mdata; + HRESULT hr = DecodeDDSHeader(header, bytesRead, flags, mdata, convFlags); + if (FAILED(hr)) + return hr; + + DWORD offset = MAX_HEADER_SIZE; + + if (!(convFlags & CONV_FLAGS_DX10)) + { + // Must reset file position since we read more than the standard header above + LARGE_INTEGER filePos = { { sizeof(uint32_t) + sizeof(DDS_HEADER), 0 } }; + if (!SetFilePointerEx(hFile.get(), filePos, 0, FILE_BEGIN)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + offset = sizeof(uint32_t) + sizeof(DDS_HEADER); + } + + std::unique_ptr pal8; + if (convFlags & CONV_FLAGS_PAL8) + { + pal8.reset(new (std::nothrow) uint32_t[256]); + if (!pal8) + { + return E_OUTOFMEMORY; + } + + if (!ReadFile(hFile.get(), pal8.get(), 256 * sizeof(uint32_t), &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesRead != (256 * sizeof(uint32_t))) + { + return E_FAIL; + } + + offset += (256 * sizeof(uint32_t)); + } + + DWORD remaining = fileInfo.EndOfFile.LowPart - offset; + if (remaining == 0) + return E_FAIL; + + hr = image.Initialize(mdata); + if (FAILED(hr)) + return hr; + + if ((convFlags & CONV_FLAGS_EXPAND) || (flags & (DDS_FLAGS_LEGACY_DWORD | DDS_FLAGS_BAD_DXTN_TAILS))) + { + std::unique_ptr temp(new (std::nothrow) uint8_t[remaining]); + if (!temp) + { + image.Release(); + return E_OUTOFMEMORY; + } + + if (!ReadFile(hFile.get(), temp.get(), remaining, &bytesRead, nullptr)) + { + image.Release(); + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesRead != remaining) + { + image.Release(); + return E_FAIL; + } + + DWORD cflags = CP_FLAGS_NONE; + if (flags & DDS_FLAGS_LEGACY_DWORD) + { + cflags |= CP_FLAGS_LEGACY_DWORD; + } + if (flags & DDS_FLAGS_BAD_DXTN_TAILS) + { + cflags |= CP_FLAGS_BAD_DXTN_TAILS; + } + + hr = CopyImage(temp.get(), + remaining, + mdata, + cflags, + convFlags, + pal8.get(), + image); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + } + else + { + if (remaining < image.GetPixelsSize()) + { + image.Release(); + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + if (!ReadFile(hFile.get(), image.GetPixels(), static_cast(image.GetPixelsSize()), &bytesRead, nullptr)) + { + image.Release(); + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (convFlags & (CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA)) + { + // Swizzle/copy image in place + hr = CopyImageInPlace(convFlags, image); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + } + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a DDS file to memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToDDSMemory( + const Image* images, + size_t nimages, + const TexMetadata& metadata, + DWORD flags, + Blob& blob) +{ + if (!images || (nimages == 0)) + return E_INVALIDARG; + + // Determine memory required + size_t required = 0; + HRESULT hr = _EncodeDDSHeader(metadata, flags, 0, 0, required); + if (FAILED(hr)) + return hr; + + bool fastpath = true; + + for (size_t i = 0; i < nimages; ++i) + { + if (!images[i].pixels) + return E_POINTER; + + if (images[i].format != metadata.format) + return E_FAIL; + + size_t ddsRowPitch, ddsSlicePitch; + ComputePitch(metadata.format, images[i].width, images[i].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE); + + assert(images[i].rowPitch > 0); + assert(images[i].slicePitch > 0); + + if ((images[i].rowPitch != ddsRowPitch) || (images[i].slicePitch != ddsSlicePitch)) + { + fastpath = false; + } + + required += ddsSlicePitch; + } + + assert(required > 0); + + blob.Release(); + + hr = blob.Initialize(required); + if (FAILED(hr)) + return hr; + + auto pDestination = reinterpret_cast(blob.GetBufferPointer()); + assert(pDestination); + + hr = _EncodeDDSHeader(metadata, flags, pDestination, blob.GetBufferSize(), required); + if (FAILED(hr)) + { + blob.Release(); + return hr; + } + + size_t remaining = blob.GetBufferSize() - required; + pDestination += required; + + if (!remaining) + { + blob.Release(); + return E_FAIL; + } + + switch (metadata.dimension) + { + case DDS_DIMENSION_TEXTURE1D: + case DDS_DIMENSION_TEXTURE2D: + { + size_t index = 0; + for (size_t item = 0; item < metadata.arraySize; ++item) + { + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + if (index >= nimages) + { + blob.Release(); + return E_FAIL; + } + + if (fastpath) + { + size_t pixsize = images[index].slicePitch; + if (memcpy_s(pDestination, remaining, images[index].pixels, pixsize)) + { + blob.Release(); + return E_FAIL; + } + + pDestination += pixsize; + remaining -= pixsize; + } + else + { + size_t ddsRowPitch, ddsSlicePitch; + ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE); + + size_t rowPitch = images[index].rowPitch; + + const uint8_t * __restrict sPtr = images[index].pixels; + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + + size_t lines = ComputeScanlines(metadata.format, images[index].height); + size_t csize = std::min(rowPitch, ddsRowPitch); + size_t tremaining = remaining; + for (size_t j = 0; j < lines; ++j) + { + if (memcpy_s(dPtr, tremaining, sPtr, csize)) + { + blob.Release(); + return E_FAIL; + } + + sPtr += rowPitch; + dPtr += ddsRowPitch; + tremaining -= ddsRowPitch; + } + + pDestination += ddsSlicePitch; + remaining -= ddsSlicePitch; + } + + ++index; + } + } + } + break; + + case DDS_DIMENSION_TEXTURE3D: + { + if (metadata.arraySize != 1) + { + blob.Release(); + return E_FAIL; + } + + size_t d = metadata.depth; + + size_t index = 0; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + for (size_t slice = 0; slice < d; ++slice) + { + if (index >= nimages) + { + blob.Release(); + return E_FAIL; + } + + if (fastpath) + { + size_t pixsize = images[index].slicePitch; + if (memcpy_s(pDestination, remaining, images[index].pixels, pixsize)) + { + blob.Release(); + return E_FAIL; + } + + pDestination += pixsize; + remaining -= pixsize; + } + else + { + size_t ddsRowPitch, ddsSlicePitch; + ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE); + + size_t rowPitch = images[index].rowPitch; + + const uint8_t * __restrict sPtr = images[index].pixels; + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + + size_t lines = ComputeScanlines(metadata.format, images[index].height); + size_t csize = std::min(rowPitch, ddsRowPitch); + size_t tremaining = remaining; + for (size_t j = 0; j < lines; ++j) + { + if (memcpy_s(dPtr, tremaining, sPtr, csize)) + { + blob.Release(); + return E_FAIL; + } + + sPtr += rowPitch; + dPtr += ddsRowPitch; + tremaining -= ddsRowPitch; + } + + pDestination += ddsSlicePitch; + remaining -= ddsSlicePitch; + } + + ++index; + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + blob.Release(); + return E_FAIL; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a DDS file to disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToDDSFile( + const Image* images, + size_t nimages, + const TexMetadata& metadata, + DWORD flags, + const wchar_t* szFile) +{ + if (!szFile) + return E_INVALIDARG; + + // Create DDS Header + const size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); + uint8_t header[MAX_HEADER_SIZE]; + size_t required; + HRESULT hr = _EncodeDDSHeader(metadata, flags, header, MAX_HEADER_SIZE, required); + if (FAILED(hr)) + return hr; + + // Create file and write header +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + auto_delete_file delonfail(hFile.get()); + + DWORD bytesWritten; + if (!WriteFile(hFile.get(), header, static_cast(required), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != required) + { + return E_FAIL; + } + + // Write images + switch (metadata.dimension) + { + case DDS_DIMENSION_TEXTURE1D: + case DDS_DIMENSION_TEXTURE2D: + { + size_t index = 0; + for (size_t item = 0; item < metadata.arraySize; ++item) + { + for (size_t level = 0; level < metadata.mipLevels; ++level, ++index) + { + if (index >= nimages) + return E_FAIL; + + if (!images[index].pixels) + return E_POINTER; + + assert(images[index].rowPitch > 0); + assert(images[index].slicePitch > 0); + + size_t ddsRowPitch, ddsSlicePitch; + ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE); + + if (images[index].slicePitch == ddsSlicePitch) + { + if (!WriteFile(hFile.get(), images[index].pixels, static_cast(ddsSlicePitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != ddsSlicePitch) + { + return E_FAIL; + } + } + else + { + size_t rowPitch = images[index].rowPitch; + if (rowPitch < ddsRowPitch) + { + // DDS uses 1-byte alignment, so if this is happening then the input pitch isn't actually a full line of data + return E_FAIL; + } + + const uint8_t * __restrict sPtr = images[index].pixels; + + size_t lines = ComputeScanlines(metadata.format, images[index].height); + for (size_t j = 0; j < lines; ++j) + { + if (!WriteFile(hFile.get(), sPtr, static_cast(ddsRowPitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != ddsRowPitch) + { + return E_FAIL; + } + + sPtr += rowPitch; + } + } + } + } + } + break; + + case DDS_DIMENSION_TEXTURE3D: + { + if (metadata.arraySize != 1) + return E_FAIL; + + size_t d = metadata.depth; + + size_t index = 0; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + for (size_t slice = 0; slice < d; ++slice, ++index) + { + if (index >= nimages) + return E_FAIL; + + if (!images[index].pixels) + return E_POINTER; + + assert(images[index].rowPitch > 0); + assert(images[index].slicePitch > 0); + + size_t ddsRowPitch, ddsSlicePitch; + ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE); + + if (images[index].slicePitch == ddsSlicePitch) + { + if (!WriteFile(hFile.get(), images[index].pixels, static_cast(ddsSlicePitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != ddsSlicePitch) + { + return E_FAIL; + } + } + else + { + size_t rowPitch = images[index].rowPitch; + if (rowPitch < ddsRowPitch) + { + // DDS uses 1-byte alignment, so if this is happening then the input pitch isn't actually a full line of data + return E_FAIL; + } + + const uint8_t * __restrict sPtr = images[index].pixels; + + size_t lines = ComputeScanlines(metadata.format, images[index].height); + for (size_t j = 0; j < lines; ++j) + { + if (!WriteFile(hFile.get(), sPtr, static_cast(ddsRowPitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != ddsRowPitch) + { + return E_FAIL; + } + + sPtr += rowPitch; + } + } + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + return E_FAIL; + } + + delonfail.clear(); + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexFlipRotate.cpp b/Kits/DirectXTex/DirectXTexFlipRotate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a6ad213058228980771e5b9c275f6ee29de8b5a --- /dev/null +++ b/Kits/DirectXTex/DirectXTexFlipRotate.cpp @@ -0,0 +1,343 @@ +//------------------------------------------------------------------------------------- +// DirectXTexFlipRotate.cpp +// +// DirectX Texture Library - Image flip/rotate operations +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + //------------------------------------------------------------------------------------- + // Do flip/rotate operation using WIC + //------------------------------------------------------------------------------------- + HRESULT PerformFlipRotateUsingWIC( + const Image& srcImage, + DWORD flags, + const WICPixelFormatGUID& pfGUID, + const Image& destImage) + { + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + assert(srcImage.format == destImage.format); + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr source; + HRESULT hr = pWIC->CreateBitmapFromMemory(static_cast(srcImage.width), static_cast(srcImage.height), pfGUID, + static_cast(srcImage.rowPitch), static_cast(srcImage.slicePitch), + srcImage.pixels, source.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr FR; + hr = pWIC->CreateBitmapFlipRotator(FR.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = FR->Initialize(source.Get(), static_cast(flags)); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfFR; + hr = FR->GetPixelFormat(&pfFR); + if (FAILED(hr)) + return hr; + + if (memcmp(&pfFR, &pfGUID, sizeof(GUID)) != 0) + { + // Flip/rotate should return the same format as the source... + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + UINT nwidth, nheight; + hr = FR->GetSize(&nwidth, &nheight); + if (FAILED(hr)) + return hr; + + if (destImage.width != nwidth || destImage.height != nheight) + return E_FAIL; + + hr = FR->CopyPixels(0, static_cast(destImage.rowPitch), static_cast(destImage.slicePitch), destImage.pixels); + if (FAILED(hr)) + return hr; + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Do conversion, flip/rotate using WIC, conversion cycle + //------------------------------------------------------------------------------------- + HRESULT PerformFlipRotateViaF32( + const Image& srcImage, + DWORD flags, + const Image& destImage) + { + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + assert(srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT); + assert(srcImage.format == destImage.format); + + ScratchImage temp; + HRESULT hr = _ConvertToR32G32B32A32(srcImage, temp); + if (FAILED(hr)) + return hr; + + const Image *tsrc = temp.GetImage(0, 0, 0); + if (!tsrc) + return E_POINTER; + + ScratchImage rtemp; + hr = rtemp.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *tdest = rtemp.GetImage(0, 0, 0); + if (!tdest) + return E_POINTER; + + hr = PerformFlipRotateUsingWIC(*tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest); + if (FAILED(hr)) + return hr; + + temp.Release(); + + hr = _ConvertFromR32G32B32A32(*tdest, destImage); + if (FAILED(hr)) + return hr; + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Flip/rotate image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::FlipRotate( + const Image& srcImage, + DWORD flags, + ScratchImage& image) +{ + if (!srcImage.pixels) + return E_POINTER; + + if (!flags) + return E_INVALIDARG; + + if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) + return E_INVALIDARG; + + if (IsCompressed(srcImage.format)) + { + // We don't support flip/rotate operations on compressed images + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + static_assert(static_cast(TEX_FR_ROTATE0) == static_cast(WICBitmapTransformRotate0), "TEX_FR_ROTATE0 no longer matches WIC"); + static_assert(static_cast(TEX_FR_ROTATE90) == static_cast(WICBitmapTransformRotate90), "TEX_FR_ROTATE90 no longer matches WIC"); + static_assert(static_cast(TEX_FR_ROTATE180) == static_cast(WICBitmapTransformRotate180), "TEX_FR_ROTATE180 no longer matches WIC"); + static_assert(static_cast(TEX_FR_ROTATE270) == static_cast(WICBitmapTransformRotate270), "TEX_FR_ROTATE270 no longer matches WIC"); + static_assert(static_cast(TEX_FR_FLIP_HORIZONTAL) == static_cast(WICBitmapTransformFlipHorizontal), "TEX_FR_FLIP_HORIZONTAL no longer matches WIC"); + static_assert(static_cast(TEX_FR_FLIP_VERTICAL) == static_cast(WICBitmapTransformFlipVertical), "TEX_FR_FLIP_VERTICAL no longer matches WIC"); + + // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags + switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270)) + { + case 0: + case TEX_FR_ROTATE90: + case TEX_FR_ROTATE180: + case TEX_FR_ROTATE270: + break; + + default: + return E_INVALIDARG; + } + + size_t nwidth = srcImage.width; + size_t nheight = srcImage.height; + + if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270)) + { + nwidth = srcImage.height; + nheight = srcImage.width; + } + + HRESULT hr = image.Initialize2D(srcImage.format, nwidth, nheight, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *rimage = image.GetImage(0, 0, 0); + if (!rimage) + { + image.Release(); + return E_POINTER; + } + + WICPixelFormatGUID pfGUID; + if (_DXGIToWIC(srcImage.format, pfGUID)) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = PerformFlipRotateUsingWIC(srcImage, flags, pfGUID, *rimage); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back + hr = PerformFlipRotateViaF32(srcImage, flags, *rimage); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Flip/rotate image (complex) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::FlipRotate( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DWORD flags, + ScratchImage& result) +{ + if (!srcImages || !nimages) + return E_INVALIDARG; + + if (IsCompressed(metadata.format)) + { + // We don't support flip/rotate operations on compressed images + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + static_assert(static_cast(TEX_FR_ROTATE0) == static_cast(WICBitmapTransformRotate0), "TEX_FR_ROTATE0 no longer matches WIC"); + static_assert(static_cast(TEX_FR_ROTATE90) == static_cast(WICBitmapTransformRotate90), "TEX_FR_ROTATE90 no longer matches WIC"); + static_assert(static_cast(TEX_FR_ROTATE180) == static_cast(WICBitmapTransformRotate180), "TEX_FR_ROTATE180 no longer matches WIC"); + static_assert(static_cast(TEX_FR_ROTATE270) == static_cast(WICBitmapTransformRotate270), "TEX_FR_ROTATE270 no longer matches WIC"); + static_assert(static_cast(TEX_FR_FLIP_HORIZONTAL) == static_cast(WICBitmapTransformFlipHorizontal), "TEX_FR_FLIP_HORIZONTAL no longer matches WIC"); + static_assert(static_cast(TEX_FR_FLIP_VERTICAL) == static_cast(WICBitmapTransformFlipVertical), "TEX_FR_FLIP_VERTICAL no longer matches WIC"); + + // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags + switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270)) + { + case 0: + case TEX_FR_ROTATE90: + case TEX_FR_ROTATE180: + case TEX_FR_ROTATE270: + break; + + default: + return E_INVALIDARG; + } + + TexMetadata mdata2 = metadata; + + bool flipwh = false; + if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270)) + { + flipwh = true; + mdata2.width = metadata.height; + mdata2.height = metadata.width; + } + + HRESULT hr = result.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) + { + result.Release(); + return E_FAIL; + } + + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } + + WICPixelFormatGUID pfGUID; + bool wicpf = _DXGIToWIC(metadata.format, pfGUID); + + for (size_t index = 0; index < nimages; ++index) + { + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + return E_FAIL; + + const Image& dst = dest[index]; + assert(dst.format == metadata.format); + + if (flipwh) + { + if (src.width != dst.height || src.height != dst.width) + { + result.Release(); + return E_FAIL; + } + } + else + { + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + } + + if (wicpf) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = PerformFlipRotateUsingWIC(src, flags, pfGUID, dst); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back + hr = PerformFlipRotateViaF32(src, flags, dst); + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexHDR.cpp b/Kits/DirectXTex/DirectXTexHDR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d1925ce229351f371dee20b33bae4be2e13b6a6 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexHDR.cpp @@ -0,0 +1,1114 @@ +//------------------------------------------------------------------------------------- +// DirectXTexHDR.cpp +// +// DirectX Texture Library - Radiance HDR (RGBE) file format reader/writer +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +// +// In theory HDR (RGBE) Radiance files can have any of the following data orientations +// +// +X width +Y height +// +X width -Y height +// -X width +Y height +// -X width -Y height +// +Y height +X width +// -Y height +X width +// +Y height -X width +// -Y height -X width +// +// All HDR files we've encountered are always written as "-Y height +X width", so +// we support only that one as that's what other Radiance parsing code does as well. +// + +//Uncomment to disable the use of adapative RLE encoding when writing an HDR. Used for testing only. +//#define DISABLE_COMPRESS + +//Uncomment to use "old colors" standard RLE encoding when writing an HDR. Used for testing only. +//#define WRITE_OLD_COLORS + +using namespace DirectX; + +namespace +{ + const char g_Signature[] = "#?RADIANCE"; + const char g_Format[] = "FORMAT="; + const char g_Exposure[] = "EXPOSURE="; + + const char g_sRGBE[] = "32-bit_rle_rgbe"; + const char g_sXYZE[] = "32-bit_rle_xyze"; + + const char g_Header[] = + "#?RADIANCE\n"\ + "FORMAT=32-bit_rle_rgbe\n"\ + "\n"\ + "-Y %u +X %u\n"; + + inline size_t FindEOL(const char* str, size_t maxlen) + { + size_t pos = 0; + + while (pos < maxlen) + { + if (str[pos] == '\n') + return pos; + else if (str[pos] == '\0') + return size_t(-1); + ++pos; + } + + return 0; + } + + //------------------------------------------------------------------------------------- + // Decodes HDR header + //------------------------------------------------------------------------------------- + HRESULT DecodeHDRHeader( + _In_reads_bytes_(size) const void* pSource, + size_t size, + _Out_ TexMetadata& metadata, + size_t& offset, + float& exposure) + { + if (!pSource) + return E_INVALIDARG; + + memset(&metadata, 0, sizeof(TexMetadata)); + + exposure = 1.f; + + if (size < sizeof(g_Signature)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + // Verify magic signature + if (memcmp(pSource, g_Signature, sizeof(g_Signature) - 1) != 0) + { + return E_FAIL; + } + + // Process first part of header + bool formatFound = false; + const char* info = reinterpret_cast(pSource); + while (size > 0) + { + if (*info == '\n') + { + ++info; + --size; + break; + } + + const size_t formatLen = sizeof(g_Format) - 1; + const size_t exposureLen = sizeof(g_Exposure) - 1; + if ((size > formatLen) && memcmp(info, g_Format, formatLen) == 0) + { + info += formatLen; + size -= formatLen; + + // Trim whitespace + while (*info == ' ' || *info == '\t') + { + if (--size == 0) + return E_FAIL; + ++info; + } + + static_assert(sizeof(g_sRGBE) == sizeof(g_sXYZE), "Format strings length mismatch"); + + const size_t encodingLen = sizeof(g_sRGBE) - 1; + + if (size < encodingLen) + { + return E_FAIL; + } + + if (memcmp(info, g_sRGBE, encodingLen) != 0 && memcmp(info, g_sXYZE, encodingLen) != 0) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + formatFound = true; + + size_t len = FindEOL(info, size); + if (len == size_t(-1)) + { + return E_FAIL; + } + + info += len + 1; + size -= len + 1; + } + else if ((size > exposureLen) && memcmp(info, g_Exposure, exposureLen) == 0) + { + info += exposureLen; + size -= exposureLen; + + // Trim whitespace + while (*info == ' ' || *info == '\t') + { + if (--size == 0) + return E_FAIL; + ++info; + } + + size_t len = FindEOL(info, size); + if (len == size_t(-1) + || len < 1) + { + return E_FAIL; + } + + char buff[32] = {}; + strncpy_s(buff, info, std::min(31, len)); + + float newExposure = static_cast(atof(buff)); + if ((newExposure >= 1e-12) && (newExposure <= 1e12)) + { + // Note that we ignore strange exposure values (like EXPOSURE=0) + exposure *= newExposure; + } + + info += len + 1; + size -= len + 1; + } + else + { + size_t len = FindEOL(info, size); + if (len == size_t(-1)) + { + return E_FAIL; + } + + info += len + 1; + size -= len + 1; + } + } + + if (!formatFound) + { + return E_FAIL; + } + + // Get orientation + char orient[256] = {}; + + size_t len = FindEOL(info, std::min(sizeof(orient), size - 1)); + if (len == size_t(-1) + || len <= 2) + { + return E_FAIL; + } + + strncpy_s(orient, info, len); + + if (orient[0] != '-' && orient[1] != 'Y') + { + // We only support the -Y +X orientation (see top of file) + return HRESULT_FROM_WIN32( + ((orient[0] == '+' || orient[0] == '-') && (orient[1] == 'X' || orient[1] == 'Y')) + ? ERROR_NOT_SUPPORTED : ERROR_INVALID_DATA + ); + } + + uint32_t height = 0; + if (sscanf_s(orient + 2, "%u", &height) != 1) + { + return E_FAIL; + } + + const char* ptr = orient + 2; + while (*ptr != 0 && *ptr != '-' && *ptr != '+') + ++ptr; + + if (*ptr == 0) + { + return E_FAIL; + } + else if (*ptr != '+') + { + // We only support the -Y +X orientation (see top of file) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + ++ptr; + if (*ptr == 0 || (*ptr != 'X' && *ptr != 'Y')) + { + return E_FAIL; + } + else if (*ptr != 'X') + { + // We only support the -Y +X orientation (see top of file) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + ++ptr; + uint32_t width; + if (sscanf_s(ptr, "%u", &width) != 1) + { + return E_FAIL; + } + + info += len + 1; + size -= len + 1; + + if (!width || !height) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + if (size == 0) + { + return E_FAIL; + } + + offset = info - reinterpret_cast(pSource); + + metadata.width = width; + metadata.height = height; + metadata.depth = metadata.arraySize = metadata.mipLevels = 1; + metadata.format = DXGI_FORMAT_R32G32B32A32_FLOAT; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + + return S_OK; + } + + //------------------------------------------------------------------------------------- + // FloatToRGBE + //------------------------------------------------------------------------------------- + inline void FloatToRGBE(_Out_writes_(width*4) uint8_t* pDestination, _In_reads_(width*fpp) const float* pSource, size_t width, _In_range_(3, 4) int fpp) + { + auto ePtr = pSource + width * fpp; + + for (size_t j = 0; j < width; ++j) + { + if (pSource + 2 >= ePtr) break; + float r = pSource[0] >= 0.f ? pSource[0] : 0.f; + float g = pSource[1] >= 0.f ? pSource[1] : 0.f; + float b = pSource[2] >= 0.f ? pSource[2] : 0.f; + pSource += fpp; + + const float max_xy = (r > g) ? r : g; + float max_xyz = (max_xy > b) ? max_xy : b; + + if (max_xyz > 1e-32) + { + int e; + max_xyz = frexpf(max_xyz, &e) * 256.f / max_xyz; + e += 128; + + uint8_t red = uint8_t(r * max_xyz); + uint8_t green = uint8_t(g * max_xyz); + uint8_t blue = uint8_t(b * max_xyz); + + pDestination[0] = red; + pDestination[1] = green; + pDestination[2] = blue; + pDestination[3] = (red || green || blue) ? uint8_t(e & 0xff) : 0; + } + else + { + pDestination[0] = pDestination[1] = pDestination[2] = pDestination[3] = 0; + } + + pDestination += 4; + } + } + + //------------------------------------------------------------------------------------- + // Encode using Adapative RLE + //------------------------------------------------------------------------------------- + _Success_(return > 0) + size_t EncodeRLE(_Out_writes_(width * 4) uint8_t* enc, _In_reads_(width * 4) const uint8_t* rgbe, size_t rowPitch, size_t width) + { + if (width < 8 || width > 32767) + { + // Don't try to compress too narrow or too wide scan-lines + return 0; + } + +#ifdef WRITE_OLD_COLORS + size_t encSize = 0; + + const uint8_t* scanPtr = rgbe; + for (size_t pixelCount = 0; pixelCount < width;) + { + size_t spanLen = 1; + const uint32_t* spanPtr = reinterpret_cast(scanPtr); + while (pixelCount + spanLen < width && spanLen < 32767) + { + if (spanPtr[spanLen] == *spanPtr) + { + ++spanLen; + } + else + break; + } + + if (spanLen > 2) + { + if (scanPtr[0] == 1 && scanPtr[1] == 1 && scanPtr[2] == 1) + { + return 0; + } + + if (encSize + 8 > rowPitch) + return 0; + + uint8_t rleLen = static_cast(std::min(spanLen - 1, 255)); + + enc[0] = scanPtr[0]; + enc[1] = scanPtr[1]; + enc[2] = scanPtr[2]; + enc[3] = scanPtr[3]; + enc[4] = 1; + enc[5] = 1; + enc[6] = 1; + enc[7] = rleLen; + enc += 8; + encSize += 8; + + size_t remaining = spanLen - 1 - rleLen; + + if (remaining > 0) + { + rleLen = static_cast(remaining >> 8); + + if (rleLen > 0) + { + if (encSize + 4 > rowPitch) + return 0; + + enc[0] = 1; + enc[1] = 1; + enc[2] = 1; + enc[3] = rleLen; + enc += 4; + encSize += 4; + + remaining -= (rleLen << 8); + } + + while (remaining > 0) + { + if (encSize + 4 > rowPitch) + return 0; + + enc[0] = scanPtr[0]; + enc[1] = scanPtr[1]; + enc[2] = scanPtr[2]; + enc[3] = scanPtr[3]; + enc += 4; + encSize += 4; + + --remaining; + } + } + + scanPtr += spanLen * 4; + pixelCount += spanLen; + } + else if (scanPtr[0] == 1 && scanPtr[1] == 1 && scanPtr[2] == 1) + { + return 0; + } + else + { + if (encSize + 4 > rowPitch) + return 0; + + enc[0] = scanPtr[0]; + enc[1] = scanPtr[1]; + enc[2] = scanPtr[2]; + enc[3] = scanPtr[3]; + enc += 4; + encSize += 4; + ++pixelCount; + scanPtr += 4; + } + } + + return encSize; +#else + enc[0] = 2; + enc[1] = 2; + enc[2] = uint8_t(width >> 8); + enc[3] = uint8_t(width & 0xff); + enc += 4; + size_t encSize = 4; + + uint8_t scan[128] = {}; + + for (int channel = 0; channel < 4; ++channel) + { + const uint8_t* spanPtr = rgbe + channel; + for (size_t pixelCount = 0; pixelCount < width;) + { + uint8_t spanLen = 1; + while (pixelCount + spanLen < width && spanLen < 127) + { + if (spanPtr[spanLen * 4] == *spanPtr) + { + ++spanLen; + } + else + break; + } + + if (spanLen > 1) + { + if (encSize + 2 > rowPitch) + return 0; + + enc[0] = 128 + spanLen; + enc[1] = *spanPtr; + enc += 2; + encSize += 2; + spanPtr += spanLen * 4; + pixelCount += spanLen; + } + else + { + uint8_t runLen = 1; + scan[0] = *spanPtr; + while (pixelCount + runLen < width && runLen < 127) + { + if (spanPtr[(runLen - 1) * 4] != spanPtr[runLen * 4]) + { + scan[runLen] = spanPtr[runLen * 4]; + runLen++; + } + else + break; + } + + if (encSize + runLen + 1 > rowPitch) + return 0; + + *enc++ = runLen; + memcpy(enc, scan, runLen); + enc += runLen; + encSize += runLen + 1; + spanPtr += runLen * 4; + pixelCount += runLen; + } + } + } + + return encSize; +#endif + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Obtain metadata from HDR file in memory/on disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromHDRMemory(const void* pSource, size_t size, TexMetadata& metadata) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + size_t offset; + float exposure; + return DecodeHDRHeader(pSource, size, metadata, offset, exposure); +} + +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromHDRFile(const wchar_t* szFile, TexMetadata& metadata) +{ + if (!szFile) + return E_INVALIDARG; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid HDR file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the standard header to be a valid HDR + if (fileInfo.EndOfFile.LowPart < sizeof(g_Signature)) + { + return E_FAIL; + } + + // Read the first part of the file to find the header + uint8_t header[8192]; + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, std::min(sizeof(header), fileInfo.EndOfFile.LowPart), &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + size_t offset; + float exposure; + return DecodeHDRHeader(header, bytesRead, metadata, offset, exposure); +} + + +//------------------------------------------------------------------------------------- +// Load a HDR file in memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromHDRMemory(const void* pSource, size_t size, TexMetadata* metadata, ScratchImage& image) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + image.Release(); + + size_t offset; + float exposure; + TexMetadata mdata; + HRESULT hr = DecodeHDRHeader(pSource, size, mdata, offset, exposure); + if (FAILED(hr)) + return hr; + + if (offset > size) + return E_FAIL; + + size_t remaining = size - offset; + if (remaining == 0) + return E_FAIL; + + hr = image.Initialize2D(mdata.format, mdata.width, mdata.height, 1, 1); + if (FAILED(hr)) + return hr; + + // Copy pixels + auto sourcePtr = reinterpret_cast(pSource) + offset; + + size_t pixelLen = remaining; + + const Image* img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + auto destPtr = img->pixels; + +#ifdef _DEBUG + memset(img->pixels, 0xFF, img->rowPitch * img->height); +#endif + + for (size_t scan = 0; scan < mdata.height; ++scan) + { + if (pixelLen < 4) + { + image.Release(); + return E_FAIL; + } + + uint8_t inColor[4]; + memcpy(inColor, sourcePtr, 4); + sourcePtr += 4; + pixelLen -= 4; + + auto scanLine = reinterpret_cast(destPtr); + + if (inColor[0] == 2 && inColor[1] == 2 && inColor[2] < 128) + { + // Adaptive Run Length Encoding (RLE) + if (size_t((inColor[2] << 8) + inColor[3]) != mdata.width) + { + image.Release(); + return E_FAIL; + } + + for (int channel = 0; channel < 4; ++channel) + { + auto pixelLoc = scanLine + channel; + for(size_t pixelCount = 0; pixelCount < mdata.width;) + { + if (pixelLen < 2) + { + image.Release(); + return E_FAIL; + } + + assert(sourcePtr < (reinterpret_cast(pSource) + size)); + + uint8_t runLen = *sourcePtr; + if (runLen > 128) + { + runLen &= 127; + if (pixelCount + runLen > mdata.width) + { + image.Release(); + return E_FAIL; + } + + float val = static_cast(sourcePtr[1]); + for (uint8_t j = 0; j < runLen; ++j) + { + *pixelLoc = val; + pixelLoc += 4; + } + pixelCount += runLen; + sourcePtr += 2; + pixelLen -= 2; + } + else if ((size < size_t(runLen + 1)) || ((pixelCount + runLen) > mdata.width)) + { + image.Release(); + return E_FAIL; + } + else + { + ++sourcePtr; + for (uint8_t j = 0; j < runLen; ++j) + { + float val = static_cast(*sourcePtr++); + *pixelLoc = val; + pixelLoc += 4; + } + pixelCount += runLen; + pixelLen -= runLen + 1; + } + } + } + } + else + { + auto pixelLoc = scanLine; + + float prevColor[4]; + prevColor[0] = inColor[0]; + prevColor[1] = inColor[1]; + prevColor[2] = inColor[2]; + prevColor[3] = inColor[3]; + + int bitShift = 0; + for (size_t pixelCount = 0; pixelCount < mdata.width;) + { + if (inColor[0] == 1 && inColor[1] == 1 && inColor[2] == 1) + { + if (bitShift > 24) + { + image.Release(); + return E_FAIL; + } + + // "Standard" Run Length Encoding + size_t spanLen = size_t(inColor[3]) << bitShift; + if (spanLen + pixelCount > mdata.width) + { + image.Release(); + return E_FAIL; + } + + for (size_t j = 0; j < spanLen; ++j) + { + pixelLoc[0] = prevColor[0]; + pixelLoc[1] = prevColor[1]; + pixelLoc[2] = prevColor[2]; + pixelLoc[3] = prevColor[3]; + pixelLoc += 4; + } + pixelCount += spanLen; + bitShift += 8; + } + else + { + // Uncompressed + pixelLoc[0] = prevColor[0] = inColor[0]; + pixelLoc[1] = prevColor[1] = inColor[1]; + pixelLoc[2] = prevColor[2] = inColor[2]; + pixelLoc[3] = prevColor[3] = inColor[3]; + bitShift = 0; + ++pixelCount; + pixelLoc += 4; + } + + if (pixelCount >= mdata.width) + break; + + if (pixelLen < 4) + { + image.Release(); + return E_FAIL; + } + + memcpy(inColor, sourcePtr, 4); + sourcePtr += 4; + pixelLen -= 4; + } + } + + destPtr += img->rowPitch; + } + + // Transform values + { + auto fdata = reinterpret_cast(image.GetPixels()); + + for (size_t j = 0; j < image.GetPixelsSize(); j += 16) + { + int exponent = static_cast(fdata[3]); + fdata[0] = 1.0f / exposure*ldexpf((fdata[0] + 0.5f), exponent - (128 + 8)); + fdata[1] = 1.0f / exposure*ldexpf((fdata[1] + 0.5f), exponent - (128 + 8)); + fdata[2] = 1.0f / exposure*ldexpf((fdata[2] + 0.5f), exponent - (128 + 8)); + fdata[3] = 1.f; + + fdata += 4; + } + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Load a HDR file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromHDRFile(const wchar_t* szFile, TexMetadata* metadata, ScratchImage& image) +{ + if (!szFile) + return E_INVALIDARG; + + image.Release(); + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid HDR file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the header to be a valid HDR + if (fileInfo.EndOfFile.LowPart < sizeof(g_Signature)) + { + return E_FAIL; + } + + // Read file + std::unique_ptr temp(new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart]); + if (!temp) + { + return E_OUTOFMEMORY; + } + + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), temp.get(), fileInfo.EndOfFile.LowPart, &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesRead != fileInfo.EndOfFile.LowPart) + { + return E_FAIL; + } + + return LoadFromHDRMemory(temp.get(), fileInfo.EndOfFile.LowPart, metadata, image); +} + + +//------------------------------------------------------------------------------------- +// Save a HDR file to memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToHDRMemory(const Image& image, Blob& blob) +{ + if (!image.pixels) + return E_POINTER; + + if (image.width > 32767 || image.height > 32767) + { + // Images larger than this can't be RLE encoded. They are technically allowed as + // uncompresssed, but we just don't support them. + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + int fpp; + switch (image.format) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + fpp = 4; + break; + + case DXGI_FORMAT_R32G32B32_FLOAT: + fpp = 3; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + blob.Release(); + + char header[256] = {}; + sprintf_s(header, g_Header, image.height, image.width); + + auto headerLen = static_cast(strlen(header)); + + size_t rowPitch = image.width * 4; + size_t slicePitch = image.height * rowPitch; + + HRESULT hr = blob.Initialize(headerLen + slicePitch); + if (FAILED(hr)) + return hr; + + // Copy header + auto dPtr = reinterpret_cast(blob.GetBufferPointer()); + assert(dPtr != 0); + memcpy_s(dPtr, blob.GetBufferSize(), header, headerLen); + dPtr += headerLen; + +#ifdef DISABLE_COMPRESS + // Uncompressed write + auto sPtr = reinterpret_cast(image.pixels); + for (size_t scan = 0; scan < image.height; ++scan) + { + FloatToRGBE(dPtr, reinterpret_cast(sPtr), image.width, fpp); + dPtr += rowPitch; + sPtr += image.rowPitch; + } +#else + std::unique_ptr temp(new (std::nothrow) uint8_t[rowPitch * 2]); + if (!temp) + { + blob.Release(); + return E_OUTOFMEMORY; + } + + auto rgbe = temp.get(); + auto enc = temp.get() + rowPitch; + + auto sPtr = reinterpret_cast(image.pixels); + for (size_t scan = 0; scan < image.height; ++scan) + { + FloatToRGBE(rgbe, reinterpret_cast(sPtr), image.width, fpp); + sPtr += image.rowPitch; + + size_t encSize = EncodeRLE(enc, rgbe, rowPitch, image.width); + if (encSize > 0) + { + memcpy(dPtr, enc, encSize); + dPtr += encSize; + } + else + { + memcpy(dPtr, rgbe, rowPitch); + dPtr += rowPitch; + } + } +#endif + + hr = blob.Trim(dPtr - reinterpret_cast(blob.GetBufferPointer())); + if (FAILED(hr)) + { + blob.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a HDR file to disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToHDRFile(const Image& image, const wchar_t* szFile) +{ + if (!szFile) + return E_INVALIDARG; + + if (!image.pixels) + return E_POINTER; + + if (image.width > 32767 || image.height > 32767) + { + // Images larger than this can't be RLE encoded. They are technically allowed as + // uncompresssed, but we just don't support them. + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + int fpp; + switch (image.format) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + fpp = 4; + break; + + case DXGI_FORMAT_R32G32B32_FLOAT: + fpp = 3; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Create file and write header +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + auto_delete_file delonfail(hFile.get()); + + size_t rowPitch = image.width * 4; + size_t slicePitch = image.height * rowPitch; + + if (slicePitch < 65535) + { + // For small images, it is better to create an in-memory file and write it out + Blob blob; + + HRESULT hr = SaveToHDRMemory(image, blob); + if (FAILED(hr)) + return hr; + + // Write blob + const DWORD bytesToWrite = static_cast(blob.GetBufferSize()); + DWORD bytesWritten; + if (!WriteFile(hFile.get(), blob.GetBufferPointer(), bytesToWrite, &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != bytesToWrite) + { + return E_FAIL; + } + } + else + { + // Otherwise, write the image one scanline at a time... + std::unique_ptr temp(new (std::nothrow) uint8_t[rowPitch * 2]); + if (!temp) + return E_OUTOFMEMORY; + + auto rgbe = temp.get(); + + // Write header + char header[256] = {}; + sprintf_s(header, g_Header, image.height, image.width); + + auto headerLen = static_cast(strlen(header)); + + DWORD bytesWritten; + if (!WriteFile(hFile.get(), header, headerLen, &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != headerLen) + return E_FAIL; + +#ifdef DISABLE_COMPRESS + // Uncompressed write + auto sPtr = reinterpret_cast(image.pixels); + for (size_t scan = 0; scan < image.height; ++scan) + { + FloatToRGBE(rgbe, reinterpret_cast(sPtr), image.width, fpp); + sPtr += image.rowPitch; + + if (!WriteFile(hFile.get(), rgbe, static_cast(rowPitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != rowPitch) + return E_FAIL; + } +#else + auto enc = temp.get() + rowPitch; + + auto sPtr = reinterpret_cast(image.pixels); + for (size_t scan = 0; scan < image.height; ++scan) + { + FloatToRGBE(rgbe, reinterpret_cast(sPtr), image.width, fpp); + sPtr += image.rowPitch; + + size_t encSize = EncodeRLE(enc, rgbe, rowPitch, image.width); + if (encSize > 0) + { + if (!WriteFile(hFile.get(), enc, static_cast(encSize), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != encSize) + return E_FAIL; + } + else + { + if (!WriteFile(hFile.get(), rgbe, static_cast(rowPitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != rowPitch) + return E_FAIL; + } + } +#endif + } + + delonfail.clear(); + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexImage.cpp b/Kits/DirectXTex/DirectXTexImage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a6077f77d004564a94a8f50734291e58f2d21c7 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexImage.cpp @@ -0,0 +1,801 @@ +//------------------------------------------------------------------------------------- +// DirectXTexImage.cpp +// +// DirectX Texture Library - Image container +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +namespace DirectX +{ + extern bool _CalculateMipLevels(_In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels); + extern bool _CalculateMipLevels3D(_In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels); + extern bool _IsAlphaAllOpaqueBC(_In_ const Image& cImage); +} + +using namespace DirectX; + +//------------------------------------------------------------------------------------- +// Determines number of image array entries and pixel size +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::_DetermineImageArray( + const TexMetadata& metadata, + DWORD cpFlags, + size_t& nImages, + size_t& pixelSize) +{ + assert(metadata.width > 0 && metadata.height > 0 && metadata.depth > 0); + assert(metadata.arraySize > 0); + assert(metadata.mipLevels > 0); + + size_t _pixelSize = 0; + size_t _nimages = 0; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t w = metadata.width; + size_t h = metadata.height; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags); + + _pixelSize += slicePitch; + ++_nimages; + + if (h > 1) + h >>= 1; + + if (w > 1) + w >>= 1; + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + size_t w = metadata.width; + size_t h = metadata.height; + size_t d = metadata.depth; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags); + + for (size_t slice = 0; slice < d; ++slice) + { + _pixelSize += slicePitch; + ++_nimages; + } + + if (h > 1) + h >>= 1; + + if (w > 1) + w >>= 1; + + if (d > 1) + d >>= 1; + } + } + break; + + default: + assert(false); + break; + } + + nImages = _nimages; + pixelSize = _pixelSize; +} + + +//------------------------------------------------------------------------------------- +// Fills in the image array entries +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::_SetupImageArray( + uint8_t *pMemory, + size_t pixelSize, + const TexMetadata& metadata, + DWORD cpFlags, + Image* images, + size_t nImages) +{ + assert(pMemory); + assert(pixelSize > 0); + assert(nImages > 0); + + if (!images) + return false; + + size_t index = 0; + uint8_t* pixels = pMemory; + const uint8_t* pEndBits = pMemory + pixelSize; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + if (metadata.arraySize == 0 || metadata.mipLevels == 0) + { + return false; + } + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t w = metadata.width; + size_t h = metadata.height; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + if (index >= nImages) + { + return false; + } + + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags); + + images[index].width = w; + images[index].height = h; + images[index].format = metadata.format; + images[index].rowPitch = rowPitch; + images[index].slicePitch = slicePitch; + images[index].pixels = pixels; + ++index; + + pixels += slicePitch; + if (pixels > pEndBits) + { + return false; + } + + if (h > 1) + h >>= 1; + + if (w > 1) + w >>= 1; + } + } + return true; + + case TEX_DIMENSION_TEXTURE3D: + { + if (metadata.mipLevels == 0 || metadata.depth == 0) + { + return false; + } + + size_t w = metadata.width; + size_t h = metadata.height; + size_t d = metadata.depth; + + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags); + + for (size_t slice = 0; slice < d; ++slice) + { + if (index >= nImages) + { + return false; + } + + // We use the same memory organization that Direct3D 11 needs for D3D11_SUBRESOURCE_DATA + // with all slices of a given miplevel being continuous in memory + images[index].width = w; + images[index].height = h; + images[index].format = metadata.format; + images[index].rowPitch = rowPitch; + images[index].slicePitch = slicePitch; + images[index].pixels = pixels; + ++index; + + pixels += slicePitch; + if (pixels > pEndBits) + { + return false; + } + } + + if (h > 1) + h >>= 1; + + if (w > 1) + w >>= 1; + + if (d > 1) + d >>= 1; + } + } + return true; + + default: + return false; + } +} + + +//===================================================================================== +// ScratchImage - Bitmap image container +//===================================================================================== + +ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom) +{ + if (this != &moveFrom) + { + Release(); + + m_nimages = moveFrom.m_nimages; + m_size = moveFrom.m_size; + m_metadata = moveFrom.m_metadata; + m_image = moveFrom.m_image; + m_memory = moveFrom.m_memory; + + moveFrom.m_nimages = 0; + moveFrom.m_size = 0; + moveFrom.m_image = nullptr; + moveFrom.m_memory = nullptr; + } + return *this; +} + + +//------------------------------------------------------------------------------------- +// Methods +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT ScratchImage::Initialize(const TexMetadata& mdata, DWORD flags) +{ + if (!IsValid(mdata.format)) + return E_INVALIDARG; + + if (IsPalettized(mdata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + size_t mipLevels = mdata.mipLevels; + + switch (mdata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (!mdata.width || mdata.height != 1 || mdata.depth != 1 || !mdata.arraySize) + return E_INVALIDARG; + + if (!_CalculateMipLevels(mdata.width, 1, mipLevels)) + return E_INVALIDARG; + break; + + case TEX_DIMENSION_TEXTURE2D: + if (!mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize) + return E_INVALIDARG; + + if (mdata.IsCubemap()) + { + if ((mdata.arraySize % 6) != 0) + return E_INVALIDARG; + } + + if (!_CalculateMipLevels(mdata.width, mdata.height, mipLevels)) + return E_INVALIDARG; + break; + + case TEX_DIMENSION_TEXTURE3D: + if (!mdata.width || !mdata.height || !mdata.depth || mdata.arraySize != 1) + return E_INVALIDARG; + + if (!_CalculateMipLevels3D(mdata.width, mdata.height, mdata.depth, mipLevels)) + return E_INVALIDARG; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + Release(); + + m_metadata.width = mdata.width; + m_metadata.height = mdata.height; + m_metadata.depth = mdata.depth; + m_metadata.arraySize = mdata.arraySize; + m_metadata.mipLevels = mipLevels; + m_metadata.miscFlags = mdata.miscFlags; + m_metadata.miscFlags2 = mdata.miscFlags2; + m_metadata.format = mdata.format; + m_metadata.dimension = mdata.dimension; + + size_t pixelSize, nimages; + _DetermineImageArray(m_metadata, flags, nimages, pixelSize); + + m_image = new (std::nothrow) Image[nimages]; + if (!m_image) + return E_OUTOFMEMORY; + + m_nimages = nimages; + memset(m_image, 0, sizeof(Image) * nimages); + + m_memory = reinterpret_cast(_aligned_malloc(pixelSize, 16)); + if (!m_memory) + { + Release(); + return E_OUTOFMEMORY; + } + m_size = pixelSize; + if (!_SetupImageArray(m_memory, pixelSize, m_metadata, flags, m_image, nimages)) + { + Release(); + return E_FAIL; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::Initialize1D(DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels, DWORD flags) +{ + if (!length || !arraySize) + return E_INVALIDARG; + + // 1D is a special case of the 2D case + HRESULT hr = Initialize2D(fmt, length, 1, arraySize, mipLevels, flags); + if (FAILED(hr)) + return hr; + + m_metadata.dimension = TEX_DIMENSION_TEXTURE1D; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::Initialize2D(DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels, DWORD flags) +{ + if (!IsValid(fmt) || !width || !height || !arraySize) + return E_INVALIDARG; + + if (IsPalettized(fmt)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (!_CalculateMipLevels(width, height, mipLevels)) + return E_INVALIDARG; + + Release(); + + m_metadata.width = width; + m_metadata.height = height; + m_metadata.depth = 1; + m_metadata.arraySize = arraySize; + m_metadata.mipLevels = mipLevels; + m_metadata.miscFlags = 0; + m_metadata.miscFlags2 = 0; + m_metadata.format = fmt; + m_metadata.dimension = TEX_DIMENSION_TEXTURE2D; + + size_t pixelSize, nimages; + _DetermineImageArray(m_metadata, flags, nimages, pixelSize); + + m_image = new (std::nothrow) Image[nimages]; + if (!m_image) + return E_OUTOFMEMORY; + + m_nimages = nimages; + memset(m_image, 0, sizeof(Image) * nimages); + + m_memory = reinterpret_cast(_aligned_malloc(pixelSize, 16)); + if (!m_memory) + { + Release(); + return E_OUTOFMEMORY; + } + m_size = pixelSize; + if (!_SetupImageArray(m_memory, pixelSize, m_metadata, flags, m_image, nimages)) + { + Release(); + return E_FAIL; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::Initialize3D(DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels, DWORD flags) +{ + if (!IsValid(fmt) || !width || !height || !depth) + return E_INVALIDARG; + + if (IsPalettized(fmt)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (!_CalculateMipLevels3D(width, height, depth, mipLevels)) + return E_INVALIDARG; + + Release(); + + m_metadata.width = width; + m_metadata.height = height; + m_metadata.depth = depth; + m_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures + m_metadata.mipLevels = mipLevels; + m_metadata.miscFlags = 0; + m_metadata.miscFlags2 = 0; + m_metadata.format = fmt; + m_metadata.dimension = TEX_DIMENSION_TEXTURE3D; + + size_t pixelSize, nimages; + _DetermineImageArray(m_metadata, flags, nimages, pixelSize); + + m_image = new (std::nothrow) Image[nimages]; + if (!m_image) + { + Release(); + return E_OUTOFMEMORY; + } + m_nimages = nimages; + memset(m_image, 0, sizeof(Image) * nimages); + + m_memory = reinterpret_cast(_aligned_malloc(pixelSize, 16)); + if (!m_memory) + { + Release(); + return E_OUTOFMEMORY; + } + m_size = pixelSize; + + if (!_SetupImageArray(m_memory, pixelSize, m_metadata, flags, m_image, nimages)) + { + Release(); + return E_FAIL; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeCube(DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels, DWORD flags) +{ + if (!width || !height || !nCubes) + return E_INVALIDARG; + + // A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube + HRESULT hr = Initialize2D(fmt, width, height, nCubes * 6, mipLevels, flags); + if (FAILED(hr)) + return hr; + + m_metadata.miscFlags |= TEX_MISC_TEXTURECUBE; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeFromImage(const Image& srcImage, bool allow1D, DWORD flags) +{ + HRESULT hr = (srcImage.height > 1 || !allow1D) + ? Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags) + : Initialize1D(srcImage.format, srcImage.width, 1, 1, flags); + + if (FAILED(hr)) + return hr; + + size_t rowCount = ComputeScanlines(srcImage.format, srcImage.height); + if (!rowCount) + return E_UNEXPECTED; + + const uint8_t* sptr = reinterpret_cast(srcImage.pixels); + if (!sptr) + return E_POINTER; + + auto dptr = reinterpret_cast(m_image[0].pixels); + if (!dptr) + return E_POINTER; + + size_t spitch = srcImage.rowPitch; + size_t dpitch = m_image[0].rowPitch; + + size_t size = std::min(dpitch, spitch); + + for (size_t y = 0; y < rowCount; ++y) + { + memcpy_s(dptr, dpitch, sptr, size); + sptr += spitch; + dptr += dpitch; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeArrayFromImages(const Image* images, size_t nImages, bool allow1D, DWORD flags) +{ + if (!images || !nImages) + return E_INVALIDARG; + + DXGI_FORMAT format = images[0].format; + size_t width = images[0].width; + size_t height = images[0].height; + + for (size_t index = 0; index < nImages; ++index) + { + if (!images[index].pixels) + return E_POINTER; + + if (images[index].format != format || images[index].width != width || images[index].height != height) + { + // All images must be the same format, width, and height + return E_FAIL; + } + } + + HRESULT hr = (height > 1 || !allow1D) + ? Initialize2D(format, width, height, nImages, 1, flags) + : Initialize1D(format, width, nImages, 1, flags); + + if (FAILED(hr)) + return hr; + + size_t rowCount = ComputeScanlines(format, height); + if (!rowCount) + return E_UNEXPECTED; + + for (size_t index = 0; index < nImages; ++index) + { + auto sptr = reinterpret_cast(images[index].pixels); + if (!sptr) + return E_POINTER; + + assert(index < m_nimages); + auto dptr = reinterpret_cast(m_image[index].pixels); + if (!dptr) + return E_POINTER; + + size_t spitch = images[index].rowPitch; + size_t dpitch = m_image[index].rowPitch; + + size_t size = std::min(dpitch, spitch); + + for (size_t y = 0; y < rowCount; ++y) + { + memcpy_s(dptr, dpitch, sptr, size); + sptr += spitch; + dptr += dpitch; + } + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::InitializeCubeFromImages(const Image* images, size_t nImages, DWORD flags) +{ + if (!images || !nImages) + return E_INVALIDARG; + + // A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube + if ((nImages % 6) != 0) + return E_INVALIDARG; + + HRESULT hr = InitializeArrayFromImages(images, nImages, false, flags); + if (FAILED(hr)) + return hr; + + m_metadata.miscFlags |= TEX_MISC_TEXTURECUBE; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT ScratchImage::Initialize3DFromImages(const Image* images, size_t depth, DWORD flags) +{ + if (!images || !depth) + return E_INVALIDARG; + + DXGI_FORMAT format = images[0].format; + size_t width = images[0].width; + size_t height = images[0].height; + + for (size_t slice = 0; slice < depth; ++slice) + { + if (!images[slice].pixels) + return E_POINTER; + + if (images[slice].format != format || images[slice].width != width || images[slice].height != height) + { + // All images must be the same format, width, and height + return E_FAIL; + } + } + + HRESULT hr = Initialize3D(format, width, height, depth, 1, flags); + if (FAILED(hr)) + return hr; + + size_t rowCount = ComputeScanlines(format, height); + if (!rowCount) + return E_UNEXPECTED; + + for (size_t slice = 0; slice < depth; ++slice) + { + auto sptr = reinterpret_cast(images[slice].pixels); + if (!sptr) + return E_POINTER; + + assert(slice < m_nimages); + auto dptr = reinterpret_cast(m_image[slice].pixels); + if (!dptr) + return E_POINTER; + + size_t spitch = images[slice].rowPitch; + size_t dpitch = m_image[slice].rowPitch; + + size_t size = std::min(dpitch, spitch); + + for (size_t y = 0; y < rowCount; ++y) + { + memcpy_s(dptr, dpitch, sptr, size); + sptr += spitch; + dptr += dpitch; + } + } + + return S_OK; +} + +void ScratchImage::Release() +{ + m_nimages = 0; + m_size = 0; + + if (m_image) + { + delete[] m_image; + m_image = nullptr; + } + + if (m_memory) + { + _aligned_free(m_memory); + m_memory = nullptr; + } + + memset(&m_metadata, 0, sizeof(m_metadata)); +} + +_Use_decl_annotations_ +bool ScratchImage::OverrideFormat(DXGI_FORMAT f) +{ + if (!m_image) + return false; + + if (!IsValid(f) || IsPlanar(f) || IsPalettized(f)) + return false; + + for (size_t index = 0; index < m_nimages; ++index) + { + m_image[index].format = f; + } + + m_metadata.format = f; + + return true; +} + +_Use_decl_annotations_ +const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const +{ + if (mip >= m_metadata.mipLevels) + return nullptr; + + size_t index = 0; + + switch (m_metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + if (slice > 0) + return nullptr; + + if (item >= m_metadata.arraySize) + return nullptr; + + index = item*(m_metadata.mipLevels) + mip; + break; + + case TEX_DIMENSION_TEXTURE3D: + if (item > 0) + { + // No support for arrays of volumes + return nullptr; + } + else + { + size_t d = m_metadata.depth; + + for (size_t level = 0; level < mip; ++level) + { + index += d; + if (d > 1) + d >>= 1; + } + + if (slice >= d) + return nullptr; + + index += slice; + } + break; + + default: + return nullptr; + } + + return &m_image[index]; +} + +bool ScratchImage::IsAlphaAllOpaque() const +{ + if (!m_image) + return false; + + if (!HasAlpha(m_metadata.format)) + return true; + + if (IsCompressed(m_metadata.format)) + { + for (size_t index = 0; index < m_nimages; ++index) + { + if (!_IsAlphaAllOpaqueBC(m_image[index])) + return false; + } + } + else + { + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*m_metadata.width), 16))); + if (!scanline) + return false; + + static const XMVECTORF32 threshold = { { { 0.99f, 0.99f, 0.99f, 0.99f } } }; + + for (size_t index = 0; index < m_nimages; ++index) + { +#pragma warning( suppress : 6011 ) + const Image& img = m_image[index]; + + const uint8_t *pPixels = img.pixels; + assert(pPixels); + + for (size_t h = 0; h < img.height; ++h) + { + if (!_LoadScanline(scanline.get(), img.width, pPixels, img.rowPitch, img.format)) + return false; + + const XMVECTOR* ptr = scanline.get(); + for (size_t w = 0; w < img.width; ++w) + { + XMVECTOR alpha = XMVectorSplatW(*ptr); + if (XMVector4Less(alpha, threshold)) + return false; + ++ptr; + } + + pPixels += img.rowPitch; + } + } + } + + return true; +} diff --git a/Kits/DirectXTex/DirectXTexMipMaps.cpp b/Kits/DirectXTex/DirectXTexMipMaps.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d330cc82286c1d9303978990d277976378fb63b --- /dev/null +++ b/Kits/DirectXTex/DirectXTexMipMaps.cpp @@ -0,0 +1,3139 @@ +//------------------------------------------------------------------------------------- +// DirectXTexMipMaps.cpp +// +// DirectX Texture Library - Mip-map generation +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "filters.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + inline bool ispow2(_In_ size_t x) + { + return ((x != 0) && !(x & (x - 1))); + } + + + size_t _CountMips(_In_ size_t width, _In_ size_t height) + { + size_t mipLevels = 1; + + while (height > 1 || width > 1) + { + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + ++mipLevels; + } + + return mipLevels; + } + + + size_t _CountMips3D(_In_ size_t width, _In_ size_t height, _In_ size_t depth) + { + size_t mipLevels = 1; + + while (height > 1 || width > 1 || depth > 1) + { + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + if (depth > 1) + depth >>= 1; + + ++mipLevels; + } + + return mipLevels; + } + + + HRESULT EnsureWicBitmapPixelFormat( + _In_ IWICImagingFactory* pWIC, + _In_ IWICBitmap* src, + _In_ DWORD filter, + _In_ const WICPixelFormatGUID& desiredPixelFormat, + _Deref_out_ IWICBitmap** dest) + { + if (!pWIC || !src || !dest) + return E_POINTER; + + *dest = nullptr; + + WICPixelFormatGUID actualPixelFormat; + HRESULT hr = src->GetPixelFormat(&actualPixelFormat); + + if (SUCCEEDED(hr)) + { + if (memcmp(&actualPixelFormat, &desiredPixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { + src->AddRef(); + *dest = src; + } + else + { + ComPtr converter; + hr = pWIC->CreateFormatConverter(converter.GetAddressOf()); + + if (SUCCEEDED(hr)) + { + BOOL canConvert = FALSE; + hr = converter->CanConvert(actualPixelFormat, desiredPixelFormat, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + } + + if (SUCCEEDED(hr)) + { + hr = converter->Initialize(src, desiredPixelFormat, _GetWICDither(filter), nullptr, 0, WICBitmapPaletteTypeMedianCut); + } + + if (SUCCEEDED(hr)) + { + hr = pWIC->CreateBitmapFromSource(converter.Get(), WICBitmapCacheOnDemand, dest); + } + } + } + + return hr; + } +} + + +namespace DirectX +{ + bool _CalculateMipLevels(_In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels) + { + if (mipLevels > 1) + { + size_t maxMips = _CountMips(width, height); + if (mipLevels > maxMips) + return false; + } + else if (mipLevels == 0) + { + mipLevels = _CountMips(width, height); + } + else + { + mipLevels = 1; + } + return true; + } + + bool _CalculateMipLevels3D(_In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels) + { + if (mipLevels > 1) + { + size_t maxMips = _CountMips3D(width, height, depth); + if (mipLevels > maxMips) + return false; + } + else if (mipLevels == 0) + { + mipLevels = _CountMips3D(width, height, depth); + } + else + { + mipLevels = 1; + } + return true; + } + + //--- Resizing color and alpha channels separately using WIC --- + HRESULT _ResizeSeparateColorAndAlpha( + _In_ IWICImagingFactory* pWIC, + _In_ bool iswic2, + _In_ IWICBitmap* original, + _In_ size_t newWidth, + _In_ size_t newHeight, + _In_ DWORD filter, + _Inout_ const Image* img) + { + if (!pWIC || !original || !img) + return E_POINTER; + + const WICBitmapInterpolationMode interpolationMode = _GetWICInterp(filter); + + WICPixelFormatGUID desiredPixelFormat = GUID_WICPixelFormatUndefined; + HRESULT hr = original->GetPixelFormat(&desiredPixelFormat); + + size_t colorBytesInPixel = 0; + size_t colorBytesPerPixel = 0; + size_t colorWithAlphaBytesPerPixel = 0; + WICPixelFormatGUID colorPixelFormat = GUID_WICPixelFormatUndefined; + WICPixelFormatGUID colorWithAlphaPixelFormat = GUID_WICPixelFormatUndefined; + + if (SUCCEEDED(hr)) + { + ComPtr componentInfo; + hr = pWIC->CreateComponentInfo(desiredPixelFormat, componentInfo.GetAddressOf()); + + ComPtr pixelFormatInfo; + if (SUCCEEDED(hr)) + { + hr = componentInfo.As(&pixelFormatInfo); + } + + UINT bitsPerPixel = 0; + if (SUCCEEDED(hr)) + { + hr = pixelFormatInfo->GetBitsPerPixel(&bitsPerPixel); + } + + if (SUCCEEDED(hr)) + { + if (bitsPerPixel <= 32) + { + colorBytesInPixel = colorBytesPerPixel = 3; + colorPixelFormat = GUID_WICPixelFormat24bppBGR; + + colorWithAlphaBytesPerPixel = 4; + colorWithAlphaPixelFormat = GUID_WICPixelFormat32bppBGRA; + } + else + { +#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + if (iswic2) + { + colorBytesInPixel = colorBytesPerPixel = 12; + colorPixelFormat = GUID_WICPixelFormat96bppRGBFloat; + } + else +#else + UNREFERENCED_PARAMETER(iswic2); +#endif + { + colorBytesInPixel = 12; + colorBytesPerPixel = 16; + colorPixelFormat = GUID_WICPixelFormat128bppRGBFloat; + } + + colorWithAlphaBytesPerPixel = 16; + colorWithAlphaPixelFormat = GUID_WICPixelFormat128bppRGBAFloat; + } + } + } + + // Resize color only image (no alpha channel) + ComPtr resizedColor; + if (SUCCEEDED(hr)) + { + ComPtr colorScaler; + hr = pWIC->CreateBitmapScaler(colorScaler.GetAddressOf()); + if (SUCCEEDED(hr)) + { + ComPtr converted; + hr = EnsureWicBitmapPixelFormat(pWIC, original, filter, colorPixelFormat, converted.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = colorScaler->Initialize(converted.Get(), static_cast(newWidth), static_cast(newHeight), interpolationMode); + } + } + + if (SUCCEEDED(hr)) + { + ComPtr resized; + hr = pWIC->CreateBitmapFromSource(colorScaler.Get(), WICBitmapCacheOnDemand, resized.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = EnsureWicBitmapPixelFormat(pWIC, resized.Get(), filter, colorPixelFormat, resizedColor.GetAddressOf()); + } + } + } + + // Resize color+alpha image + ComPtr resizedColorWithAlpha; + if (SUCCEEDED(hr)) + { + ComPtr colorWithAlphaScaler; + hr = pWIC->CreateBitmapScaler(colorWithAlphaScaler.GetAddressOf()); + if (SUCCEEDED(hr)) + { + ComPtr converted; + hr = EnsureWicBitmapPixelFormat(pWIC, original, filter, colorWithAlphaPixelFormat, converted.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = colorWithAlphaScaler->Initialize(converted.Get(), static_cast(newWidth), static_cast(newHeight), interpolationMode); + } + } + + if (SUCCEEDED(hr)) + { + ComPtr resized; + hr = pWIC->CreateBitmapFromSource(colorWithAlphaScaler.Get(), WICBitmapCacheOnDemand, resized.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = EnsureWicBitmapPixelFormat(pWIC, resized.Get(), filter, colorWithAlphaPixelFormat, resizedColorWithAlpha.GetAddressOf()); + } + } + } + + // Merge pixels (copying color channels from color only image to color+alpha image) + if (SUCCEEDED(hr)) + { + ComPtr colorLock; + ComPtr colorWithAlphaLock; + hr = resizedColor->Lock(nullptr, WICBitmapLockRead, colorLock.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = resizedColorWithAlpha->Lock(nullptr, WICBitmapLockWrite, colorWithAlphaLock.GetAddressOf()); + } + + if (SUCCEEDED(hr)) + { + WICInProcPointer colorWithAlphaData = nullptr; + UINT colorWithAlphaSizeInBytes = 0; + UINT colorWithAlphaStride = 0; + + hr = colorWithAlphaLock->GetDataPointer(&colorWithAlphaSizeInBytes, &colorWithAlphaData); + if (SUCCEEDED(hr)) + { + if (!colorWithAlphaData) + { + hr = E_POINTER; + } + else + { + hr = colorWithAlphaLock->GetStride(&colorWithAlphaStride); + } + } + + WICInProcPointer colorData = nullptr; + UINT colorSizeInBytes = 0; + UINT colorStride = 0; + if (SUCCEEDED(hr)) + { + hr = colorLock->GetDataPointer(&colorSizeInBytes, &colorData); + if (SUCCEEDED(hr)) + { + if (!colorData) + { + hr = E_POINTER; + } + else + { + hr = colorLock->GetStride(&colorStride); + } + } + } + + for (size_t j = 0; SUCCEEDED(hr) && j < newHeight; j++) + { + for (size_t i = 0; SUCCEEDED(hr) && i < newWidth; i++) + { + size_t colorWithAlphaIndex = (j * colorWithAlphaStride) + (i * colorWithAlphaBytesPerPixel); + size_t colorIndex = (j * colorStride) + (i * colorBytesPerPixel); + + if (((colorWithAlphaIndex + colorBytesInPixel) > colorWithAlphaSizeInBytes) + || ((colorIndex + colorBytesPerPixel) > colorSizeInBytes)) + { + hr = E_INVALIDARG; + } + else + { +#pragma warning( suppress : 26014 6386 ) // No overflow possible here + memcpy_s(colorWithAlphaData + colorWithAlphaIndex, colorWithAlphaBytesPerPixel, colorData + colorIndex, colorBytesInPixel); + } + } + } + } + } + + if (SUCCEEDED(hr)) + { + ComPtr wicBitmap; + hr = EnsureWicBitmapPixelFormat(pWIC, resizedColorWithAlpha.Get(), filter, desiredPixelFormat, wicBitmap.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = wicBitmap->CopyPixels(nullptr, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + } + } + + return hr; + } +} + +namespace +{ + //--- determine when to use WIC vs. non-WIC paths --- + bool UseWICFiltering(_In_ DXGI_FORMAT format, _In_ DWORD filter) + { + if (filter & TEX_FILTER_FORCE_NON_WIC) + { + // Explicit flag indicates use of non-WIC code paths + return false; + } + + if (filter & TEX_FILTER_FORCE_WIC) + { + // Explicit flag to use WIC code paths, skips all the case checks below + return true; + } + + if (IsSRGB(format) || (filter & TEX_FILTER_SRGB)) + { + // Use non-WIC code paths for sRGB correct filtering + return false; + } + +#if defined(_XBOX_ONE) && defined(_TITLE) + if (format == DXGI_FORMAT_R16G16B16A16_FLOAT + || format == DXGI_FORMAT_R16_FLOAT) + { + // Use non-WIC code paths as these conversions are not supported by Xbox One XDK + return false; + } +#endif + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + switch (filter & TEX_FILTER_MASK) + { + case TEX_FILTER_LINEAR: + if (filter & TEX_FILTER_WRAP) + { + // WIC only supports 'clamp' semantics (MIRROR is equivalent to clamp for linear) + return false; + } + + if (BitsPerColor(format) > 8) + { + // Avoid the WIC bitmap scaler when doing Linear filtering of XR/HDR formats + return false; + } + break; + + case TEX_FILTER_CUBIC: + if (filter & (TEX_FILTER_WRAP | TEX_FILTER_MIRROR)) + { + // WIC only supports 'clamp' semantics + return false; + } + + if (BitsPerColor(format) > 8) + { + // Avoid the WIC bitmap scaler when doing Cubic filtering of XR/HDR formats + return false; + } + break; + + case TEX_FILTER_TRIANGLE: + // WIC does not implement this filter + return false; + } + + return true; + } + + + //--- mipmap (1D/2D) generation using WIC image scalar --- + HRESULT GenerateMipMapsUsingWIC( + _In_ const Image& baseImage, + _In_ DWORD filter, + _In_ size_t levels, + _In_ const WICPixelFormatGUID& pfGUID, + _In_ const ScratchImage& mipChain, + _In_ size_t item) + { + assert(levels > 1); + + if (!baseImage.pixels || !mipChain.GetPixels()) + return E_POINTER; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + size_t width = baseImage.width; + size_t height = baseImage.height; + + ComPtr source; + HRESULT hr = pWIC->CreateBitmapFromMemory(static_cast(width), static_cast(height), pfGUID, + static_cast(baseImage.rowPitch), static_cast(baseImage.slicePitch), + baseImage.pixels, source.GetAddressOf()); + if (FAILED(hr)) + return hr; + + // Copy base image to top miplevel + const Image *img0 = mipChain.GetImage(0, item, 0); + if (!img0) + return E_POINTER; + + uint8_t* pDest = img0->pixels; + if (!pDest) + return E_POINTER; + + const uint8_t *pSrc = baseImage.pixels; + for (size_t h = 0; h < height; ++h) + { + size_t msize = std::min(img0->rowPitch, baseImage.rowPitch); + memcpy_s(pDest, img0->rowPitch, pSrc, msize); + pSrc += baseImage.rowPitch; + pDest += img0->rowPitch; + } + + ComPtr componentInfo; + hr = pWIC->CreateComponentInfo(pfGUID, componentInfo.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr pixelFormatInfo; + hr = componentInfo.As(&pixelFormatInfo); + if (FAILED(hr)) + return hr; + + BOOL supportsTransparency = FALSE; + hr = pixelFormatInfo->SupportsTransparency(&supportsTransparency); + if (FAILED(hr)) + return hr; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + const Image *img = mipChain.GetImage(level, item, 0); + if (!img) + return E_POINTER; + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + assert(img->width == width && img->height == height && img->format == baseImage.format); + + if ((filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency) + { + hr = _ResizeSeparateColorAndAlpha(pWIC, iswic2, source.Get(), width, height, filter, img); + if (FAILED(hr)) + return hr; + } + else + { + ComPtr scaler; + hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(source.Get(), static_cast(width), static_cast(height), _GetWICInterp(filter)); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&pfScaler, &pfGUID, sizeof(WICPixelFormatGUID)) == 0) + { + hr = scaler->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + else + { + // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we + // convert it back + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfScaler, pfGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(scaler.Get(), pfGUID, _GetWICDither(filter), nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + } + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Generate (1D/2D) mip-map helpers (custom filtering) + //------------------------------------------------------------------------------------- + HRESULT Setup2DMips( + _In_reads_(nimages) const Image* baseImages, + _In_ size_t nimages, + _In_ const TexMetadata& mdata, + _Out_ ScratchImage& mipChain) + { + if (!baseImages || !nimages) + return E_INVALIDARG; + + assert(mdata.mipLevels > 1); + assert(mdata.arraySize == nimages); + assert(mdata.depth == 1 && mdata.dimension != TEX_DIMENSION_TEXTURE3D); + assert(mdata.width == baseImages[0].width); + assert(mdata.height == baseImages[0].height); + assert(mdata.format == baseImages[0].format); + + HRESULT hr = mipChain.Initialize(mdata); + if (FAILED(hr)) + return hr; + + // Copy base image(s) to top of mip chain + for (size_t item = 0; item < nimages; ++item) + { + const Image& src = baseImages[item]; + + const Image *dest = mipChain.GetImage(0, item, 0); + if (!dest) + { + mipChain.Release(); + return E_POINTER; + } + + assert(src.format == dest->format); + + uint8_t* pDest = dest->pixels; + if (!pDest) + { + mipChain.Release(); + return E_POINTER; + } + + const uint8_t *pSrc = src.pixels; + size_t rowPitch = src.rowPitch; + for (size_t h = 0; h < mdata.height; ++h) + { + size_t msize = std::min(dest->rowPitch, rowPitch); + memcpy_s(pDest, dest->rowPitch, pSrc, msize); + pSrc += rowPitch; + pDest += dest->rowPitch; + } + } + + return S_OK; + } + + //--- 2D Point Filter --- + HRESULT Generate2DMipsPointFilter(size_t levels, const ScratchImage& mipChain, size_t item) + { + if (!mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate temporary space (2 scanlines) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 2), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row = target + width; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR)*width); +#endif + + // 2D point filter + const Image* src = mipChain.GetImage(level - 1, item, 0); + const Image* dest = mipChain.GetImage(level, item, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + size_t nheight = (height > 1) ? (height >> 1) : 1; + + size_t xinc = (width << 16) / nwidth; + size_t yinc = (height << 16) / nheight; + + size_t lasty = size_t(-1); + + size_t sy = 0; + for (size_t y = 0; y < nheight; ++y) + { + if ((lasty ^ sy) >> 16) + { + if (!_LoadScanline(row, width, pSrc + (rowPitch * (sy >> 16)), rowPitch, src->format)) + return E_FAIL; + lasty = sy; + } + + size_t sx = 0; + for (size_t x = 0; x < nwidth; ++x) + { + target[x] = row[sx >> 16]; + sx += xinc; + } + + if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth)) + return E_FAIL; + pDest += dest->rowPitch; + + sy += yinc; + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + } + + return S_OK; + } + + + //--- 2D Box Filter --- + HRESULT Generate2DMipsBoxFilter(size_t levels, DWORD filter, const ScratchImage& mipChain, size_t item) + { + if (!mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + if (!ispow2(width) || !ispow2(height)) + return E_FAIL; + + // Allocate temporary space (3 scanlines) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 3), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* urow0 = target + width; + XMVECTOR* urow1 = target + width * 2; + + const XMVECTOR* urow2 = urow0 + 1; + const XMVECTOR* urow3 = urow1 + 1; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + if (height <= 1) + { + urow1 = urow0; + } + + if (width <= 1) + { + urow2 = urow0; + urow3 = urow1; + } + + // 2D box filter + const Image* src = mipChain.GetImage(level - 1, item, 0); + const Image* dest = mipChain.GetImage(level, item, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + size_t nheight = (height > 1) ? (height >> 1) : 1; + + for (size_t y = 0; y < nheight; ++y) + { + if (!_LoadScanlineLinear(urow0, width, pSrc, rowPitch, src->format, filter)) + return E_FAIL; + pSrc += rowPitch; + + if (urow0 != urow1) + { + if (!_LoadScanlineLinear(urow1, width, pSrc, rowPitch, src->format, filter)) + return E_FAIL; + pSrc += rowPitch; + } + + for (size_t x = 0; x < nwidth; ++x) + { + size_t x2 = x << 1; + + AVERAGE4(target[x], urow0[x2], urow1[x2], urow2[x2], urow3[x2]); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + } + + return S_OK; + } + + + //--- 2D Linear Filter --- + HRESULT Generate2DMipsLinearFilter(size_t levels, DWORD filter, const ScratchImage& mipChain, size_t item) + { + if (!mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate temporary space (3 scanlines, plus X and Y filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 3), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr lf(new (std::nothrow) LinearFilter[width + height]); + if (!lf) + return E_OUTOFMEMORY; + + LinearFilter* lfX = lf.get(); + LinearFilter* lfY = lf.get() + width; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row0 = target + width; + XMVECTOR* row1 = target + width * 2; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + // 2D linear filter + const Image* src = mipChain.GetImage(level - 1, item, 0); + const Image* dest = mipChain.GetImage(level, item, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + _CreateLinearFilter(width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, lfX); + + size_t nheight = (height > 1) ? (height >> 1) : 1; + _CreateLinearFilter(height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, lfY); + +#ifdef _DEBUG + memset(row0, 0xCD, sizeof(XMVECTOR)*width); + memset(row1, 0xDD, sizeof(XMVECTOR)*width); +#endif + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + + for (size_t y = 0; y < nheight; ++y) + { + auto& toY = lfY[y]; + + if (toY.u0 != u0) + { + if (toY.u0 != u1) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(row0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter)) + return E_FAIL; + } + else + { + u0 = u1; + u1 = size_t(-1); + + std::swap(row0, row1); + } + } + + if (toY.u1 != u1) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(row1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < nwidth; ++x) + { + auto& toX = lfX[x]; + + BILINEAR_INTERPOLATE(target[x], toX, toY, row0, row1); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + } + + return S_OK; + } + + //--- 2D Cubic Filter --- + HRESULT Generate2DMipsCubicFilter(size_t levels, DWORD filter, const ScratchImage& mipChain, size_t item) + { + if (!mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate temporary space (5 scanlines, plus X and Y filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 5), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr cf(new (std::nothrow) CubicFilter[width + height]); + if (!cf) + return E_OUTOFMEMORY; + + CubicFilter* cfX = cf.get(); + CubicFilter* cfY = cf.get() + width; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row0 = target + width; + XMVECTOR* row1 = target + width * 2; + XMVECTOR* row2 = target + width * 3; + XMVECTOR* row3 = target + width * 4; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + // 2D cubic filter + const Image* src = mipChain.GetImage(level - 1, item, 0); + const Image* dest = mipChain.GetImage(level, item, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + _CreateCubicFilter(width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, (filter & TEX_FILTER_MIRROR_U) != 0, cfX); + + size_t nheight = (height > 1) ? (height >> 1) : 1; + _CreateCubicFilter(height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, (filter & TEX_FILTER_MIRROR_V) != 0, cfY); + +#ifdef _DEBUG + memset(row0, 0xCD, sizeof(XMVECTOR)*width); + memset(row1, 0xDD, sizeof(XMVECTOR)*width); + memset(row2, 0xED, sizeof(XMVECTOR)*width); + memset(row3, 0xFD, sizeof(XMVECTOR)*width); +#endif + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + size_t u2 = size_t(-1); + size_t u3 = size_t(-1); + + for (size_t y = 0; y < nheight; ++y) + { + auto& toY = cfY[y]; + + // Scanline 1 + if (toY.u0 != u0) + { + if (toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(row0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter)) + return E_FAIL; + } + else if (toY.u0 == u1) + { + u0 = u1; + u1 = size_t(-1); + + std::swap(row0, row1); + } + else if (toY.u0 == u2) + { + u0 = u2; + u2 = size_t(-1); + + std::swap(row0, row2); + } + else if (toY.u0 == u3) + { + u0 = u3; + u3 = size_t(-1); + + std::swap(row0, row3); + } + } + + // Scanline 2 + if (toY.u1 != u1) + { + if (toY.u1 != u2 && toY.u1 != u3) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(row1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter)) + return E_FAIL; + } + else if (toY.u1 == u2) + { + u1 = u2; + u2 = size_t(-1); + + std::swap(row1, row2); + } + else if (toY.u1 == u3) + { + u1 = u3; + u3 = size_t(-1); + + std::swap(row1, row3); + } + } + + // Scanline 3 + if (toY.u2 != u2) + { + if (toY.u2 != u3) + { + u2 = toY.u2; + + if (!_LoadScanlineLinear(row2, width, pSrc + (rowPitch * u2), rowPitch, src->format, filter)) + return E_FAIL; + } + else + { + u2 = u3; + u3 = size_t(-1); + + std::swap(row2, row3); + } + } + + // Scanline 4 + if (toY.u3 != u3) + { + u3 = toY.u3; + + if (!_LoadScanlineLinear(row3, width, pSrc + (rowPitch * u3), rowPitch, src->format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < nwidth; ++x) + { + auto& toX = cfX[x]; + + XMVECTOR C0, C1, C2, C3; + + CUBIC_INTERPOLATE(C0, toX.x, row0[toX.u0], row0[toX.u1], row0[toX.u2], row0[toX.u3]); + CUBIC_INTERPOLATE(C1, toX.x, row1[toX.u0], row1[toX.u1], row1[toX.u2], row1[toX.u3]); + CUBIC_INTERPOLATE(C2, toX.x, row2[toX.u0], row2[toX.u1], row2[toX.u2], row2[toX.u3]); + CUBIC_INTERPOLATE(C3, toX.x, row3[toX.u0], row3[toX.u1], row3[toX.u2], row3[toX.u3]); + + CUBIC_INTERPOLATE(target[x], toY.x, C0, C1, C2, C3); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + } + + return S_OK; + } + + + //--- 2D Triangle Filter --- + HRESULT Generate2DMipsTriangleFilter(size_t levels, DWORD filter, const ScratchImage& mipChain, size_t item) + { + if (!mipChain.GetImages()) + return E_INVALIDARG; + + using namespace TriangleFilter; + + // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate initial temporary space (1 scanline, accumulation rows, plus X and Y filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * width, 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr rowActive(new (std::nothrow) TriangleRow[height]); + if (!rowActive) + return E_OUTOFMEMORY; + + TriangleRow * rowFree = nullptr; + + std::unique_ptr tfX, tfY; + + XMVECTOR* row = scanline.get(); + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + // 2D triangle filter + const Image* src = mipChain.GetImage(level - 1, item, 0); + const Image* dest = mipChain.GetImage(level, item, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + size_t rowPitch = src->rowPitch; + const uint8_t* pEndSrc = pSrc + rowPitch * height; + + uint8_t* pDest = dest->pixels; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + HRESULT hr = _Create(width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, tfX); + if (FAILED(hr)) + return hr; + + size_t nheight = (height > 1) ? (height >> 1) : 1; + hr = _Create(height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, tfY); + if (FAILED(hr)) + return hr; + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR)*width); +#endif + + auto xFromEnd = reinterpret_cast(reinterpret_cast(tfX.get()) + tfX->sizeInBytes); + auto yFromEnd = reinterpret_cast(reinterpret_cast(tfY.get()) + tfY->sizeInBytes); + + // Count times rows get written (and clear out any leftover accumulation rows from last miplevel) + for (FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; ) + { + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < nheight); + TriangleRow* rowAcc = &rowActive[v]; + + ++rowAcc->remaining; + + if (rowAcc->scanline) + { + memset(rowAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth); + } + } + + yFrom = reinterpret_cast(reinterpret_cast(yFrom) + yFrom->sizeInBytes); + } + + // Filter image + for (FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; ) + { + // Create accumulation rows as needed + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < nheight); + TriangleRow* rowAcc = &rowActive[v]; + + if (!rowAcc->scanline) + { + if (rowFree) + { + // Steal and reuse scanline from 'free row' list + // (it will always be at least as wide as nwidth due to loop decending order) + assert(rowFree->scanline != 0); + rowAcc->scanline.reset(rowFree->scanline.release()); + rowFree = rowFree->next; + } + else + { + rowAcc->scanline.reset(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * nwidth, 16))); + if (!rowAcc->scanline) + return E_OUTOFMEMORY; + } + + memset(rowAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth); + } + } + + // Load source scanline + if ((pSrc + rowPitch) > pEndSrc) + return E_FAIL; + + if (!_LoadScanlineLinear(row, width, pSrc, rowPitch, src->format, filter)) + return E_FAIL; + + pSrc += rowPitch; + + // Process row + size_t x = 0; + for (FilterFrom* xFrom = tfX->from; xFrom < xFromEnd; ++x) + { + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < nheight); + float yweight = yFrom->to[j].weight; + + XMVECTOR* accPtr = rowActive[v].scanline.get(); + if (!accPtr) + return E_POINTER; + + for (size_t k = 0; k < xFrom->count; ++k) + { + size_t u = xFrom->to[k].u; + assert(u < nwidth); + + XMVECTOR weight = XMVectorReplicate(yweight * xFrom->to[k].weight); + + assert(x < width); + accPtr[u] = XMVectorMultiplyAdd(row[x], weight, accPtr[u]); + } + } + + xFrom = reinterpret_cast(reinterpret_cast(xFrom) + xFrom->sizeInBytes); + } + + // Write completed accumulation rows + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < nheight); + TriangleRow* rowAcc = &rowActive[v]; + + assert(rowAcc->remaining > 0); + --rowAcc->remaining; + + if (!rowAcc->remaining) + { + XMVECTOR* pAccSrc = rowAcc->scanline.get(); + if (!pAccSrc) + return E_POINTER; + + switch (dest->format) + { + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + { + // Need to slightly bias results for floating-point error accumulation which can + // be visible with harshly quantized values + static const XMVECTORF32 Bias = { { { 0.f, 0.f, 0.f, 0.1f } } }; + + XMVECTOR* ptr = pAccSrc; + for (size_t i = 0; i < dest->width; ++i, ++ptr) + { + *ptr = XMVectorAdd(*ptr, Bias); + } + } + break; + + default: + break; + } + + // This performs any required clamping + if (!_StoreScanlineLinear(pDest + (dest->rowPitch * v), dest->rowPitch, dest->format, pAccSrc, dest->width, filter)) + return E_FAIL; + + // Put row on freelist to reuse it's allocated scanline + rowAcc->next = rowFree; + rowFree = rowAcc; + } + } + + yFrom = reinterpret_cast(reinterpret_cast(yFrom) + yFrom->sizeInBytes); + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Generate volume mip-map helpers + //------------------------------------------------------------------------------------- + HRESULT Setup3DMips( + _In_reads_(depth) const Image* baseImages, + size_t depth, + size_t levels, + _Out_ ScratchImage& mipChain) + { + if (!baseImages || !depth) + return E_INVALIDARG; + + assert(levels > 1); + + size_t width = baseImages[0].width; + size_t height = baseImages[0].height; + + HRESULT hr = mipChain.Initialize3D(baseImages[0].format, width, height, depth, levels); + if (FAILED(hr)) + return hr; + + // Copy base images to top slice + for (size_t slice = 0; slice < depth; ++slice) + { + const Image& src = baseImages[slice]; + + const Image *dest = mipChain.GetImage(0, 0, slice); + if (!dest) + { + mipChain.Release(); + return E_POINTER; + } + + assert(src.format == dest->format); + + uint8_t* pDest = dest->pixels; + if (!pDest) + { + mipChain.Release(); + return E_POINTER; + } + + const uint8_t *pSrc = src.pixels; + size_t rowPitch = src.rowPitch; + for (size_t h = 0; h < height; ++h) + { + size_t msize = std::min(dest->rowPitch, rowPitch); + memcpy_s(pDest, dest->rowPitch, pSrc, msize); + pSrc += rowPitch; + pDest += dest->rowPitch; + } + } + + return S_OK; + } + + + //--- 3D Point Filter --- + HRESULT Generate3DMipsPointFilter(size_t depth, size_t levels, const ScratchImage& mipChain) + { + if (!depth || !mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate temporary space (2 scanlines) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 2), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row = target + width; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR)*width); +#endif + + if (depth > 1) + { + // 3D point filter + size_t ndepth = depth >> 1; + + size_t zinc = (depth << 16) / ndepth; + + size_t sz = 0; + for (size_t slice = 0; slice < ndepth; ++slice) + { + const Image* src = mipChain.GetImage(level - 1, 0, (sz >> 16)); + const Image* dest = mipChain.GetImage(level, 0, slice); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + size_t nheight = (height > 1) ? (height >> 1) : 1; + + size_t xinc = (width << 16) / nwidth; + size_t yinc = (height << 16) / nheight; + + size_t lasty = size_t(-1); + + size_t sy = 0; + for (size_t y = 0; y < nheight; ++y) + { + if ((lasty ^ sy) >> 16) + { + if (!_LoadScanline(row, width, pSrc + (rowPitch * (sy >> 16)), rowPitch, src->format)) + return E_FAIL; + lasty = sy; + } + + size_t sx = 0; + for (size_t x = 0; x < nwidth; ++x) + { + target[x] = row[sx >> 16]; + sx += xinc; + } + + if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth)) + return E_FAIL; + pDest += dest->rowPitch; + + sy += yinc; + } + + sz += zinc; + } + } + else + { + // 2D point filter + const Image* src = mipChain.GetImage(level - 1, 0, 0); + const Image* dest = mipChain.GetImage(level, 0, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + size_t nheight = (height > 1) ? (height >> 1) : 1; + + size_t xinc = (width << 16) / nwidth; + size_t yinc = (height << 16) / nheight; + + size_t lasty = size_t(-1); + + size_t sy = 0; + for (size_t y = 0; y < nheight; ++y) + { + if ((lasty ^ sy) >> 16) + { + if (!_LoadScanline(row, width, pSrc + (rowPitch * (sy >> 16)), rowPitch, src->format)) + return E_FAIL; + lasty = sy; + } + + size_t sx = 0; + for (size_t x = 0; x < nwidth; ++x) + { + target[x] = row[sx >> 16]; + sx += xinc; + } + + if (!_StoreScanline(pDest, dest->rowPitch, dest->format, target, nwidth)) + return E_FAIL; + pDest += dest->rowPitch; + + sy += yinc; + } + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + if (depth > 1) + depth >>= 1; + } + + return S_OK; + } + + + //--- 3D Box Filter --- + HRESULT Generate3DMipsBoxFilter(size_t depth, size_t levels, DWORD filter, const ScratchImage& mipChain) + { + if (!depth || !mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + if (!ispow2(width) || !ispow2(height) || !ispow2(depth)) + return E_FAIL; + + // Allocate temporary space (5 scanlines) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 5), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* urow0 = target + width; + XMVECTOR* urow1 = target + width * 2; + XMVECTOR* vrow0 = target + width * 3; + XMVECTOR* vrow1 = target + width * 4; + + const XMVECTOR* urow2 = urow0 + 1; + const XMVECTOR* urow3 = urow1 + 1; + const XMVECTOR* vrow2 = vrow0 + 1; + const XMVECTOR* vrow3 = vrow1 + 1; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + if (height <= 1) + { + urow1 = urow0; + vrow1 = vrow0; + } + + if (width <= 1) + { + urow2 = urow0; + urow3 = urow1; + vrow2 = vrow0; + vrow3 = vrow1; + } + + if (depth > 1) + { + // 3D box filter + size_t ndepth = depth >> 1; + + for (size_t slice = 0; slice < ndepth; ++slice) + { + size_t slicea = std::min(slice * 2, depth - 1); + size_t sliceb = std::min(slicea + 1, depth - 1); + + const Image* srca = mipChain.GetImage(level - 1, 0, slicea); + const Image* srcb = mipChain.GetImage(level - 1, 0, sliceb); + const Image* dest = mipChain.GetImage(level, 0, slice); + + if (!srca || !srcb || !dest) + return E_POINTER; + + const uint8_t* pSrc1 = srca->pixels; + const uint8_t* pSrc2 = srcb->pixels; + uint8_t* pDest = dest->pixels; + + size_t aRowPitch = srca->rowPitch; + size_t bRowPitch = srcb->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + size_t nheight = (height > 1) ? (height >> 1) : 1; + + for (size_t y = 0; y < nheight; ++y) + { + if (!_LoadScanlineLinear(urow0, width, pSrc1, aRowPitch, srca->format, filter)) + return E_FAIL; + pSrc1 += aRowPitch; + + if (urow0 != urow1) + { + if (!_LoadScanlineLinear(urow1, width, pSrc1, aRowPitch, srca->format, filter)) + return E_FAIL; + pSrc1 += aRowPitch; + } + + if (!_LoadScanlineLinear(vrow0, width, pSrc2, bRowPitch, srcb->format, filter)) + return E_FAIL; + pSrc2 += bRowPitch; + + if (vrow0 != vrow1) + { + if (!_LoadScanlineLinear(vrow1, width, pSrc2, bRowPitch, srcb->format, filter)) + return E_FAIL; + pSrc2 += bRowPitch; + } + + for (size_t x = 0; x < nwidth; ++x) + { + size_t x2 = x << 1; + + AVERAGE8(target[x], urow0[x2], urow1[x2], urow2[x2], urow3[x2], + vrow0[x2], vrow1[x2], vrow2[x2], vrow3[x2]); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + } + } + else + { + // 2D box filter + const Image* src = mipChain.GetImage(level - 1, 0, 0); + const Image* dest = mipChain.GetImage(level, 0, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t nwidth = (width > 1) ? (width >> 1) : 1; + size_t nheight = (height > 1) ? (height >> 1) : 1; + + for (size_t y = 0; y < nheight; ++y) + { + if (!_LoadScanlineLinear(urow0, width, pSrc, rowPitch, src->format, filter)) + return E_FAIL; + pSrc += rowPitch; + + if (urow0 != urow1) + { + if (!_LoadScanlineLinear(urow1, width, pSrc, rowPitch, src->format, filter)) + return E_FAIL; + pSrc += rowPitch; + } + + for (size_t x = 0; x < nwidth; ++x) + { + size_t x2 = x << 1; + + AVERAGE4(target[x], urow0[x2], urow1[x2], urow2[x2], urow3[x2]); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + if (depth > 1) + depth >>= 1; + } + + return S_OK; + } + + + //--- 3D Linear Filter --- + HRESULT Generate3DMipsLinearFilter(size_t depth, size_t levels, DWORD filter, const ScratchImage& mipChain) + { + if (!depth || !mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate temporary space (5 scanlines, plus X/Y/Z filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 5), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr lf(new (std::nothrow) LinearFilter[width + height + depth]); + if (!lf) + return E_OUTOFMEMORY; + + LinearFilter* lfX = lf.get(); + LinearFilter* lfY = lf.get() + width; + LinearFilter* lfZ = lf.get() + width + height; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* urow0 = target + width; + XMVECTOR* urow1 = target + width * 2; + XMVECTOR* vrow0 = target + width * 3; + XMVECTOR* vrow1 = target + width * 4; + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + size_t nwidth = (width > 1) ? (width >> 1) : 1; + _CreateLinearFilter(width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, lfX); + + size_t nheight = (height > 1) ? (height >> 1) : 1; + _CreateLinearFilter(height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, lfY); + +#ifdef _DEBUG + memset(urow0, 0xCD, sizeof(XMVECTOR)*width); + memset(urow1, 0xDD, sizeof(XMVECTOR)*width); + memset(vrow0, 0xED, sizeof(XMVECTOR)*width); + memset(vrow1, 0xFD, sizeof(XMVECTOR)*width); +#endif + + if (depth > 1) + { + // 3D linear filter + size_t ndepth = depth >> 1; + _CreateLinearFilter(depth, ndepth, (filter & TEX_FILTER_WRAP_W) != 0, lfZ); + + for (size_t slice = 0; slice < ndepth; ++slice) + { + auto& toZ = lfZ[slice]; + + const Image* srca = mipChain.GetImage(level - 1, 0, toZ.u0); + const Image* srcb = mipChain.GetImage(level - 1, 0, toZ.u1); + if (!srca || !srcb) + return E_POINTER; + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + + const Image* dest = mipChain.GetImage(level, 0, slice); + if (!dest) + return E_POINTER; + + uint8_t* pDest = dest->pixels; + + for (size_t y = 0; y < nheight; ++y) + { + auto& toY = lfY[y]; + + if (toY.u0 != u0) + { + if (toY.u0 != u1) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(urow0, width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format, filter) + || !_LoadScanlineLinear(vrow0, width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format, filter)) + return E_FAIL; + } + else + { + u0 = u1; + u1 = size_t(-1); + + std::swap(urow0, urow1); + std::swap(vrow0, vrow1); + } + } + + if (toY.u1 != u1) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(urow1, width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format, filter) + || !_LoadScanlineLinear(vrow1, width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < nwidth; ++x) + { + auto& toX = lfX[x]; + + TRILINEAR_INTERPOLATE(target[x], toX, toY, toZ, urow0, urow1, vrow0, vrow1); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + } + } + else + { + // 2D linear filter + const Image* src = mipChain.GetImage(level - 1, 0, 0); + const Image* dest = mipChain.GetImage(level, 0, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + + for (size_t y = 0; y < nheight; ++y) + { + auto& toY = lfY[y]; + + if (toY.u0 != u0) + { + if (toY.u0 != u1) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(urow0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter)) + return E_FAIL; + } + else + { + u0 = u1; + u1 = size_t(-1); + + std::swap(urow0, urow1); + } + } + + if (toY.u1 != u1) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(urow1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < nwidth; ++x) + { + auto& toX = lfX[x]; + + BILINEAR_INTERPOLATE(target[x], toX, toY, urow0, urow1); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + if (depth > 1) + depth >>= 1; + } + + return S_OK; + } + + + //--- 3D Cubic Filter --- + HRESULT Generate3DMipsCubicFilter(size_t depth, size_t levels, DWORD filter, const ScratchImage& mipChain) + { + if (!depth || !mipChain.GetImages()) + return E_INVALIDARG; + + // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate temporary space (17 scanlines, plus X/Y/Z filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 17), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr cf(new (std::nothrow) CubicFilter[width + height + depth]); + if (!cf) + return E_OUTOFMEMORY; + + CubicFilter* cfX = cf.get(); + CubicFilter* cfY = cf.get() + width; + CubicFilter* cfZ = cf.get() + width + height; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* urow[4]; + XMVECTOR* vrow[4]; + XMVECTOR* srow[4]; + XMVECTOR* trow[4]; + + XMVECTOR *ptr = scanline.get() + width; + for (size_t j = 0; j < 4; ++j) + { + urow[j] = ptr; ptr += width; + vrow[j] = ptr; ptr += width; + srow[j] = ptr; ptr += width; + trow[j] = ptr; ptr += width; + } + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + size_t nwidth = (width > 1) ? (width >> 1) : 1; + _CreateCubicFilter(width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, (filter & TEX_FILTER_MIRROR_U) != 0, cfX); + + size_t nheight = (height > 1) ? (height >> 1) : 1; + _CreateCubicFilter(height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, (filter & TEX_FILTER_MIRROR_V) != 0, cfY); + +#ifdef _DEBUG + for (size_t j = 0; j < 4; ++j) + { + memset(urow[j], 0xCD, sizeof(XMVECTOR)*width); + memset(vrow[j], 0xDD, sizeof(XMVECTOR)*width); + memset(srow[j], 0xED, sizeof(XMVECTOR)*width); + memset(trow[j], 0xFD, sizeof(XMVECTOR)*width); + } +#endif + + if (depth > 1) + { + // 3D cubic filter + size_t ndepth = depth >> 1; + _CreateCubicFilter(depth, ndepth, (filter & TEX_FILTER_WRAP_W) != 0, (filter & TEX_FILTER_MIRROR_W) != 0, cfZ); + + for (size_t slice = 0; slice < ndepth; ++slice) + { + auto& toZ = cfZ[slice]; + + const Image* srca = mipChain.GetImage(level - 1, 0, toZ.u0); + const Image* srcb = mipChain.GetImage(level - 1, 0, toZ.u1); + const Image* srcc = mipChain.GetImage(level - 1, 0, toZ.u2); + const Image* srcd = mipChain.GetImage(level - 1, 0, toZ.u3); + if (!srca || !srcb || !srcc || !srcd) + return E_POINTER; + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + size_t u2 = size_t(-1); + size_t u3 = size_t(-1); + + const Image* dest = mipChain.GetImage(level, 0, slice); + if (!dest) + return E_POINTER; + + uint8_t* pDest = dest->pixels; + + for (size_t y = 0; y < nheight; ++y) + { + auto& toY = cfY[y]; + + // Scanline 1 + if (toY.u0 != u0) + { + if (toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(urow[0], width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format, filter) + || !_LoadScanlineLinear(urow[1], width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format, filter) + || !_LoadScanlineLinear(urow[2], width, srcc->pixels + (srcc->rowPitch * u0), srcc->rowPitch, srcc->format, filter) + || !_LoadScanlineLinear(urow[3], width, srcd->pixels + (srcd->rowPitch * u0), srcd->rowPitch, srcd->format, filter)) + return E_FAIL; + } + else if (toY.u0 == u1) + { + u0 = u1; + u1 = size_t(-1); + + std::swap(urow[0], vrow[0]); + std::swap(urow[1], vrow[1]); + std::swap(urow[2], vrow[2]); + std::swap(urow[3], vrow[3]); + } + else if (toY.u0 == u2) + { + u0 = u2; + u2 = size_t(-1); + + std::swap(urow[0], srow[0]); + std::swap(urow[1], srow[1]); + std::swap(urow[2], srow[2]); + std::swap(urow[3], srow[3]); + } + else if (toY.u0 == u3) + { + u0 = u3; + u3 = size_t(-1); + + std::swap(urow[0], trow[0]); + std::swap(urow[1], trow[1]); + std::swap(urow[2], trow[2]); + std::swap(urow[3], trow[3]); + } + } + + // Scanline 2 + if (toY.u1 != u1) + { + if (toY.u1 != u2 && toY.u1 != u3) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(vrow[0], width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format, filter) + || !_LoadScanlineLinear(vrow[1], width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format, filter) + || !_LoadScanlineLinear(vrow[2], width, srcc->pixels + (srcc->rowPitch * u1), srcc->rowPitch, srcc->format, filter) + || !_LoadScanlineLinear(vrow[3], width, srcd->pixels + (srcd->rowPitch * u1), srcd->rowPitch, srcd->format, filter)) + return E_FAIL; + } + else if (toY.u1 == u2) + { + u1 = u2; + u2 = size_t(-1); + + std::swap(vrow[0], srow[0]); + std::swap(vrow[1], srow[1]); + std::swap(vrow[2], srow[2]); + std::swap(vrow[3], srow[3]); + } + else if (toY.u1 == u3) + { + u1 = u3; + u3 = size_t(-1); + + std::swap(vrow[0], trow[0]); + std::swap(vrow[1], trow[1]); + std::swap(vrow[2], trow[2]); + std::swap(vrow[3], trow[3]); + } + } + + // Scanline 3 + if (toY.u2 != u2) + { + if (toY.u2 != u3) + { + u2 = toY.u2; + + if (!_LoadScanlineLinear(srow[0], width, srca->pixels + (srca->rowPitch * u2), srca->rowPitch, srca->format, filter) + || !_LoadScanlineLinear(srow[1], width, srcb->pixels + (srcb->rowPitch * u2), srcb->rowPitch, srcb->format, filter) + || !_LoadScanlineLinear(srow[2], width, srcc->pixels + (srcc->rowPitch * u2), srcc->rowPitch, srcc->format, filter) + || !_LoadScanlineLinear(srow[3], width, srcd->pixels + (srcd->rowPitch * u2), srcd->rowPitch, srcd->format, filter)) + return E_FAIL; + } + else + { + u2 = u3; + u3 = size_t(-1); + + std::swap(srow[0], trow[0]); + std::swap(srow[1], trow[1]); + std::swap(srow[2], trow[2]); + std::swap(srow[3], trow[3]); + } + } + + // Scanline 4 + if (toY.u3 != u3) + { + u3 = toY.u3; + + if (!_LoadScanlineLinear(trow[0], width, srca->pixels + (srca->rowPitch * u3), srca->rowPitch, srca->format, filter) + || !_LoadScanlineLinear(trow[1], width, srcb->pixels + (srcb->rowPitch * u3), srcb->rowPitch, srcb->format, filter) + || !_LoadScanlineLinear(trow[2], width, srcc->pixels + (srcc->rowPitch * u3), srcc->rowPitch, srcc->format, filter) + || !_LoadScanlineLinear(trow[3], width, srcd->pixels + (srcd->rowPitch * u3), srcd->rowPitch, srcd->format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < nwidth; ++x) + { + auto& toX = cfX[x]; + + XMVECTOR D[4]; + + for (size_t j = 0; j < 4; ++j) + { + XMVECTOR C0, C1, C2, C3; + CUBIC_INTERPOLATE(C0, toX.x, urow[j][toX.u0], urow[j][toX.u1], urow[j][toX.u2], urow[j][toX.u3]); + CUBIC_INTERPOLATE(C1, toX.x, vrow[j][toX.u0], vrow[j][toX.u1], vrow[j][toX.u2], vrow[j][toX.u3]); + CUBIC_INTERPOLATE(C2, toX.x, srow[j][toX.u0], srow[j][toX.u1], srow[j][toX.u2], srow[j][toX.u3]); + CUBIC_INTERPOLATE(C3, toX.x, trow[j][toX.u0], trow[j][toX.u1], trow[j][toX.u2], trow[j][toX.u3]); + + CUBIC_INTERPOLATE(D[j], toY.x, C0, C1, C2, C3); + } + + CUBIC_INTERPOLATE(target[x], toZ.x, D[0], D[1], D[2], D[3]); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + } + } + else + { + // 2D cubic filter + const Image* src = mipChain.GetImage(level - 1, 0, 0); + const Image* dest = mipChain.GetImage(level, 0, 0); + + if (!src || !dest) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + uint8_t* pDest = dest->pixels; + + size_t rowPitch = src->rowPitch; + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + size_t u2 = size_t(-1); + size_t u3 = size_t(-1); + + for (size_t y = 0; y < nheight; ++y) + { + auto& toY = cfY[y]; + + // Scanline 1 + if (toY.u0 != u0) + { + if (toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(urow[0], width, pSrc + (rowPitch * u0), rowPitch, src->format, filter)) + return E_FAIL; + } + else if (toY.u0 == u1) + { + u0 = u1; + u1 = size_t(-1); + + std::swap(urow[0], vrow[0]); + } + else if (toY.u0 == u2) + { + u0 = u2; + u2 = size_t(-1); + + std::swap(urow[0], srow[0]); + } + else if (toY.u0 == u3) + { + u0 = u3; + u3 = size_t(-1); + + std::swap(urow[0], trow[0]); + } + } + + // Scanline 2 + if (toY.u1 != u1) + { + if (toY.u1 != u2 && toY.u1 != u3) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(vrow[0], width, pSrc + (rowPitch * u1), rowPitch, src->format, filter)) + return E_FAIL; + } + else if (toY.u1 == u2) + { + u1 = u2; + u2 = size_t(-1); + + std::swap(vrow[0], srow[0]); + } + else if (toY.u1 == u3) + { + u1 = u3; + u3 = size_t(-1); + + std::swap(vrow[0], trow[0]); + } + } + + // Scanline 3 + if (toY.u2 != u2) + { + if (toY.u2 != u3) + { + u2 = toY.u2; + + if (!_LoadScanlineLinear(srow[0], width, pSrc + (rowPitch * u2), rowPitch, src->format, filter)) + return E_FAIL; + } + else + { + u2 = u3; + u3 = size_t(-1); + + std::swap(srow[0], trow[0]); + } + } + + // Scanline 4 + if (toY.u3 != u3) + { + u3 = toY.u3; + + if (!_LoadScanlineLinear(trow[0], width, pSrc + (rowPitch * u3), rowPitch, src->format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < nwidth; ++x) + { + auto& toX = cfX[x]; + + XMVECTOR C0, C1, C2, C3; + CUBIC_INTERPOLATE(C0, toX.x, urow[0][toX.u0], urow[0][toX.u1], urow[0][toX.u2], urow[0][toX.u3]); + CUBIC_INTERPOLATE(C1, toX.x, vrow[0][toX.u0], vrow[0][toX.u1], vrow[0][toX.u2], vrow[0][toX.u3]); + CUBIC_INTERPOLATE(C2, toX.x, srow[0][toX.u0], srow[0][toX.u1], srow[0][toX.u2], srow[0][toX.u3]); + CUBIC_INTERPOLATE(C3, toX.x, trow[0][toX.u0], trow[0][toX.u1], trow[0][toX.u2], trow[0][toX.u3]); + + CUBIC_INTERPOLATE(target[x], toY.x, C0, C1, C2, C3); + } + + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, target, nwidth, filter)) + return E_FAIL; + pDest += dest->rowPitch; + } + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + if (depth > 1) + depth >>= 1; + } + + return S_OK; + } + + + //--- 3D Triangle Filter --- + HRESULT Generate3DMipsTriangleFilter(size_t depth, size_t levels, DWORD filter, const ScratchImage& mipChain) + { + if (!depth || !mipChain.GetImages()) + return E_INVALIDARG; + + using namespace TriangleFilter; + + // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips) + + assert(levels > 1); + + size_t width = mipChain.GetMetadata().width; + size_t height = mipChain.GetMetadata().height; + + // Allocate initial temporary space (1 scanline, accumulation rows, plus X/Y/Z filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * width, 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr sliceActive(new (std::nothrow) TriangleRow[depth]); + if (!sliceActive) + return E_OUTOFMEMORY; + + TriangleRow * sliceFree = nullptr; + + std::unique_ptr tfX, tfY, tfZ; + + XMVECTOR* row = scanline.get(); + + // Resize base image to each target mip level + for (size_t level = 1; level < levels; ++level) + { + size_t nwidth = (width > 1) ? (width >> 1) : 1; + HRESULT hr = _Create(width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, tfX); + if (FAILED(hr)) + return hr; + + size_t nheight = (height > 1) ? (height >> 1) : 1; + hr = _Create(height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, tfY); + if (FAILED(hr)) + return hr; + + size_t ndepth = (depth > 1) ? (depth >> 1) : 1; + hr = _Create(depth, ndepth, (filter & TEX_FILTER_WRAP_W) != 0, tfZ); + if (FAILED(hr)) + return hr; + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR)*width); +#endif + + auto xFromEnd = reinterpret_cast(reinterpret_cast(tfX.get()) + tfX->sizeInBytes); + auto yFromEnd = reinterpret_cast(reinterpret_cast(tfY.get()) + tfY->sizeInBytes); + auto zFromEnd = reinterpret_cast(reinterpret_cast(tfZ.get()) + tfZ->sizeInBytes); + + // Count times slices get written (and clear out any leftover accumulation slices from last miplevel) + for (FilterFrom* zFrom = tfZ->from; zFrom < zFromEnd; ) + { + for (size_t j = 0; j < zFrom->count; ++j) + { + size_t w = zFrom->to[j].u; + assert(w < ndepth); + TriangleRow* sliceAcc = &sliceActive[w]; + + ++sliceAcc->remaining; + + if (sliceAcc->scanline) + { + memset(sliceAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth * nheight); + } + } + + zFrom = reinterpret_cast(reinterpret_cast(zFrom) + zFrom->sizeInBytes); + } + + // Filter image + size_t z = 0; + for (FilterFrom* zFrom = tfZ->from; zFrom < zFromEnd; ++z) + { + // Create accumulation slices as needed + for (size_t j = 0; j < zFrom->count; ++j) + { + size_t w = zFrom->to[j].u; + assert(w < ndepth); + TriangleRow* sliceAcc = &sliceActive[w]; + + if (!sliceAcc->scanline) + { + if (sliceFree) + { + // Steal and reuse scanline from 'free slice' list + // (it will always be at least as large as nwidth*nheight due to loop decending order) + assert(sliceFree->scanline != 0); + sliceAcc->scanline.reset(sliceFree->scanline.release()); + sliceFree = sliceFree->next; + } + else + { + size_t bytes = sizeof(XMVECTOR) * nwidth * nheight; + sliceAcc->scanline.reset(reinterpret_cast(_aligned_malloc(bytes, 16))); + if (!sliceAcc->scanline) + return E_OUTOFMEMORY; + } + + memset(sliceAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth * nheight); + } + } + + assert(z < depth); + const Image* src = mipChain.GetImage(level - 1, 0, z); + if (!src) + return E_POINTER; + + const uint8_t* pSrc = src->pixels; + size_t rowPitch = src->rowPitch; + const uint8_t* pEndSrc = pSrc + rowPitch * height; + + for (FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; ) + { + // Load source scanline + if ((pSrc + rowPitch) > pEndSrc) + return E_FAIL; + + if (!_LoadScanlineLinear(row, width, pSrc, rowPitch, src->format, filter)) + return E_FAIL; + + pSrc += rowPitch; + + // Process row + size_t x = 0; + for (FilterFrom* xFrom = tfX->from; xFrom < xFromEnd; ++x) + { + for (size_t j = 0; j < zFrom->count; ++j) + { + size_t w = zFrom->to[j].u; + assert(w < ndepth); + float zweight = zFrom->to[j].weight; + + XMVECTOR* accSlice = sliceActive[w].scanline.get(); + if (!accSlice) + return E_POINTER; + + for (size_t k = 0; k < yFrom->count; ++k) + { + size_t v = yFrom->to[k].u; + assert(v < nheight); + float yweight = yFrom->to[k].weight; + + XMVECTOR * accPtr = accSlice + v * nwidth; + + for (size_t l = 0; l < xFrom->count; ++l) + { + size_t u = xFrom->to[l].u; + assert(u < nwidth); + + XMVECTOR weight = XMVectorReplicate(zweight * yweight * xFrom->to[l].weight); + + assert(x < width); + accPtr[u] = XMVectorMultiplyAdd(row[x], weight, accPtr[u]); + } + } + } + + xFrom = reinterpret_cast(reinterpret_cast(xFrom) + xFrom->sizeInBytes); + } + + yFrom = reinterpret_cast(reinterpret_cast(yFrom) + yFrom->sizeInBytes); + } + + // Write completed accumulation slices + for (size_t j = 0; j < zFrom->count; ++j) + { + size_t w = zFrom->to[j].u; + assert(w < ndepth); + TriangleRow* sliceAcc = &sliceActive[w]; + + assert(sliceAcc->remaining > 0); + --sliceAcc->remaining; + + if (!sliceAcc->remaining) + { + const Image* dest = mipChain.GetImage(level, 0, w); + XMVECTOR* pAccSrc = sliceAcc->scanline.get(); + if (!dest || !pAccSrc) + return E_POINTER; + + uint8_t* pDest = dest->pixels; + + for (size_t h = 0; h < nheight; ++h) + { + switch (dest->format) + { + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + { + // Need to slightly bias results for floating-point error accumulation which can + // be visible with harshly quantized values + static const XMVECTORF32 Bias = { { { 0.f, 0.f, 0.f, 0.1f } } }; + + XMVECTOR* ptr = pAccSrc; + for (size_t i = 0; i < dest->width; ++i, ++ptr) + { + *ptr = XMVectorAdd(*ptr, Bias); + } + } + break; + + default: + break; + } + + // This performs any required clamping + if (!_StoreScanlineLinear(pDest, dest->rowPitch, dest->format, pAccSrc, dest->width, filter)) + return E_FAIL; + + pDest += dest->rowPitch; + pAccSrc += nwidth; + } + + // Put slice on freelist to reuse it's allocated scanline + sliceAcc->next = sliceFree; + sliceFree = sliceAcc; + } + } + + zFrom = reinterpret_cast(reinterpret_cast(zFrom) + zFrom->sizeInBytes); + } + + if (height > 1) + height >>= 1; + + if (width > 1) + width >>= 1; + + if (depth > 1) + depth >>= 1; + } + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Generate mipmap chain +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GenerateMipMaps( + const Image& baseImage, + DWORD filter, + size_t levels, + ScratchImage& mipChain, + bool allow1D) +{ + if (!IsValid(baseImage.format)) + return E_INVALIDARG; + + if (!baseImage.pixels) + return E_POINTER; + + if (!_CalculateMipLevels(baseImage.width, baseImage.height, levels)) + return E_INVALIDARG; + + if (levels <= 1) + return E_INVALIDARG; + + if (IsCompressed(baseImage.format) || IsTypeless(baseImage.format) || IsPlanar(baseImage.format) || IsPalettized(baseImage.format)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + HRESULT hr; + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + if (UseWICFiltering(baseImage.format, filter)) + { + //--- Use WIC filtering to generate mipmaps ----------------------------------- + switch (filter & TEX_FILTER_MASK) + { + case 0: + case TEX_FILTER_POINT: + case TEX_FILTER_FANT: // Equivalent to Box filter + case TEX_FILTER_LINEAR: + case TEX_FILTER_CUBIC: + { + static_assert(TEX_FILTER_FANT == TEX_FILTER_BOX, "TEX_FILTER_ flag alias mismatch"); + + WICPixelFormatGUID pfGUID; + if (_DXGIToWIC(baseImage.format, pfGUID, true)) + { + // Case 1: Base image format is supported by Windows Imaging Component + hr = (baseImage.height > 1 || !allow1D) + ? mipChain.Initialize2D(baseImage.format, baseImage.width, baseImage.height, 1, levels) + : mipChain.Initialize1D(baseImage.format, baseImage.width, 1, levels); + if (FAILED(hr)) + return hr; + + return GenerateMipMapsUsingWIC(baseImage, filter, levels, pfGUID, mipChain, 0); + } + else + { + // Case 2: Base image format is not supported by WIC, so we have to convert, generate, and convert back + assert(baseImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT); + ScratchImage temp; + hr = _ConvertToR32G32B32A32(baseImage, temp); + if (FAILED(hr)) + return hr; + + const Image *timg = temp.GetImage(0, 0, 0); + if (!timg) + return E_POINTER; + + ScratchImage tMipChain; + hr = (baseImage.height > 1 || !allow1D) + ? tMipChain.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, baseImage.width, baseImage.height, 1, levels) + : tMipChain.Initialize1D(DXGI_FORMAT_R32G32B32A32_FLOAT, baseImage.width, 1, levels); + if (FAILED(hr)) + return hr; + + hr = GenerateMipMapsUsingWIC(*timg, filter, levels, GUID_WICPixelFormat128bppRGBAFloat, tMipChain, 0); + if (FAILED(hr)) + return hr; + + temp.Release(); + + return _ConvertFromR32G32B32A32(tMipChain.GetImages(), tMipChain.GetImageCount(), tMipChain.GetMetadata(), baseImage.format, mipChain); + } + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + else + { + //--- Use custom filters to generate mipmaps ---------------------------------- + TexMetadata mdata = {}; + mdata.width = baseImage.width; + if (baseImage.height > 1 || !allow1D) + { + mdata.height = baseImage.height; + mdata.dimension = TEX_DIMENSION_TEXTURE2D; + } + else + { + mdata.height = 1; + mdata.dimension = TEX_DIMENSION_TEXTURE1D; + } + mdata.depth = mdata.arraySize = 1; + mdata.mipLevels = levels; + mdata.format = baseImage.format; + + DWORD filter_select = (filter & TEX_FILTER_MASK); + if (!filter_select) + { + // Default filter choice + filter_select = (ispow2(baseImage.width) && ispow2(baseImage.height)) ? TEX_FILTER_BOX : TEX_FILTER_LINEAR; + } + + switch (filter_select) + { + case TEX_FILTER_BOX: + hr = Setup2DMips(&baseImage, 1, mdata, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate2DMipsBoxFilter(levels, filter, mipChain, 0); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_POINT: + hr = Setup2DMips(&baseImage, 1, mdata, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate2DMipsPointFilter(levels, mipChain, 0); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_LINEAR: + hr = Setup2DMips(&baseImage, 1, mdata, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate2DMipsLinearFilter(levels, filter, mipChain, 0); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_CUBIC: + hr = Setup2DMips(&baseImage, 1, mdata, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate2DMipsCubicFilter(levels, filter, mipChain, 0); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_TRIANGLE: + hr = Setup2DMips(&baseImage, 1, mdata, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate2DMipsTriangleFilter(levels, filter, mipChain, 0); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } +} + +_Use_decl_annotations_ +HRESULT DirectX::GenerateMipMaps( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DWORD filter, + size_t levels, + ScratchImage& mipChain) +{ + if (!srcImages || !nimages || !IsValid(metadata.format)) + return E_INVALIDARG; + + if (metadata.IsVolumemap() + || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (!_CalculateMipLevels(metadata.width, metadata.height, levels)) + return E_INVALIDARG; + + if (levels <= 1) + return E_INVALIDARG; + + std::vector baseImages; + baseImages.reserve(metadata.arraySize); + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t index = metadata.ComputeIndex(0, item, 0); + if (index >= nimages) + return E_FAIL; + + const Image& src = srcImages[index]; + if (!src.pixels) + return E_POINTER; + + if (src.format != metadata.format || src.width != metadata.width || src.height != metadata.height) + { + // All base images must be the same format, width, and height + return E_FAIL; + } + + baseImages.push_back(src); + } + + assert(baseImages.size() == metadata.arraySize); + + HRESULT hr; + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + if (!metadata.IsPMAlpha() && UseWICFiltering(metadata.format, filter)) + { + //--- Use WIC filtering to generate mipmaps ----------------------------------- + switch (filter & TEX_FILTER_MASK) + { + case 0: + case TEX_FILTER_POINT: + case TEX_FILTER_FANT: // Equivalent to Box filter + case TEX_FILTER_LINEAR: + case TEX_FILTER_CUBIC: + { + static_assert(TEX_FILTER_FANT == TEX_FILTER_BOX, "TEX_FILTER_ flag alias mismatch"); + + WICPixelFormatGUID pfGUID; + if (_DXGIToWIC(metadata.format, pfGUID, true)) + { + // Case 1: Base image format is supported by Windows Imaging Component + TexMetadata mdata2 = metadata; + mdata2.mipLevels = levels; + hr = mipChain.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + hr = GenerateMipMapsUsingWIC(baseImages[item], filter, levels, pfGUID, mipChain, item); + if (FAILED(hr)) + { + mipChain.Release(); + return hr; + } + } + + return S_OK; + } + else + { + // Case 2: Base image format is not supported by WIC, so we have to convert, generate, and convert back + assert(metadata.format != DXGI_FORMAT_R32G32B32A32_FLOAT); + + TexMetadata mdata2 = metadata; + mdata2.mipLevels = levels; + mdata2.format = DXGI_FORMAT_R32G32B32A32_FLOAT; + ScratchImage tMipChain; + hr = tMipChain.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + ScratchImage temp; + hr = _ConvertToR32G32B32A32(baseImages[item], temp); + if (FAILED(hr)) + return hr; + + const Image *timg = temp.GetImage(0, 0, 0); + if (!timg) + return E_POINTER; + + hr = GenerateMipMapsUsingWIC(*timg, filter, levels, GUID_WICPixelFormat128bppRGBAFloat, tMipChain, item); + if (FAILED(hr)) + return hr; + } + + return _ConvertFromR32G32B32A32(tMipChain.GetImages(), tMipChain.GetImageCount(), tMipChain.GetMetadata(), metadata.format, mipChain); + } + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + else + { + //--- Use custom filters to generate mipmaps ---------------------------------- + TexMetadata mdata2 = metadata; + mdata2.mipLevels = levels; + + DWORD filter_select = (filter & TEX_FILTER_MASK); + if (!filter_select) + { + // Default filter choice + filter_select = (ispow2(metadata.width) && ispow2(metadata.height)) ? TEX_FILTER_BOX : TEX_FILTER_LINEAR; + } + + switch (filter_select) + { + case TEX_FILTER_BOX: + hr = Setup2DMips(&baseImages[0], metadata.arraySize, mdata2, mipChain); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + hr = Generate2DMipsBoxFilter(levels, filter, mipChain, item); + if (FAILED(hr)) + mipChain.Release(); + } + return hr; + + case TEX_FILTER_POINT: + hr = Setup2DMips(&baseImages[0], metadata.arraySize, mdata2, mipChain); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + hr = Generate2DMipsPointFilter(levels, mipChain, item); + if (FAILED(hr)) + mipChain.Release(); + } + return hr; + + case TEX_FILTER_LINEAR: + hr = Setup2DMips(&baseImages[0], metadata.arraySize, mdata2, mipChain); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + hr = Generate2DMipsLinearFilter(levels, filter, mipChain, item); + if (FAILED(hr)) + mipChain.Release(); + } + return hr; + + case TEX_FILTER_CUBIC: + hr = Setup2DMips(&baseImages[0], metadata.arraySize, mdata2, mipChain); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + hr = Generate2DMipsCubicFilter(levels, filter, mipChain, item); + if (FAILED(hr)) + mipChain.Release(); + } + return hr; + + case TEX_FILTER_TRIANGLE: + hr = Setup2DMips(&baseImages[0], metadata.arraySize, mdata2, mipChain); + if (FAILED(hr)) + return hr; + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + hr = Generate2DMipsTriangleFilter(levels, filter, mipChain, item); + if (FAILED(hr)) + mipChain.Release(); + } + return hr; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } +} + + +//------------------------------------------------------------------------------------- +// Generate mipmap chain for volume texture +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GenerateMipMaps3D( + const Image* baseImages, + size_t depth, + DWORD filter, + size_t levels, + ScratchImage& mipChain) +{ + if (!baseImages || !depth) + return E_INVALIDARG; + + if (filter & TEX_FILTER_FORCE_WIC) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + DXGI_FORMAT format = baseImages[0].format; + size_t width = baseImages[0].width; + size_t height = baseImages[0].height; + + if (!_CalculateMipLevels3D(width, height, depth, levels)) + return E_INVALIDARG; + + if (levels <= 1) + return E_INVALIDARG; + + for (size_t slice = 0; slice < depth; ++slice) + { + if (!baseImages[slice].pixels) + return E_POINTER; + + if (baseImages[slice].format != format || baseImages[slice].width != width || baseImages[slice].height != height) + { + // All base images must be the same format, width, and height + return E_FAIL; + } + } + + if (IsCompressed(format) || IsTypeless(format) || IsPlanar(format) || IsPalettized(format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + HRESULT hr; + + DWORD filter_select = (filter & TEX_FILTER_MASK); + if (!filter_select) + { + // Default filter choice + filter_select = (ispow2(width) && ispow2(height) && ispow2(depth)) ? TEX_FILTER_BOX : TEX_FILTER_TRIANGLE; + } + + switch (filter_select) + { + case TEX_FILTER_BOX: + hr = Setup3DMips(baseImages, depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsBoxFilter(depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_POINT: + hr = Setup3DMips(baseImages, depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsPointFilter(depth, levels, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_LINEAR: + hr = Setup3DMips(baseImages, depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsLinearFilter(depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_CUBIC: + hr = Setup3DMips(baseImages, depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsCubicFilter(depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_TRIANGLE: + hr = Setup3DMips(baseImages, depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsTriangleFilter(depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } +} + +_Use_decl_annotations_ +HRESULT DirectX::GenerateMipMaps3D( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DWORD filter, + size_t levels, + ScratchImage& mipChain) +{ + if (!srcImages || !nimages || !IsValid(metadata.format)) + return E_INVALIDARG; + + if (filter & TEX_FILTER_FORCE_WIC) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (!metadata.IsVolumemap() + || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (!_CalculateMipLevels3D(metadata.width, metadata.height, metadata.depth, levels)) + return E_INVALIDARG; + + if (levels <= 1) + return E_INVALIDARG; + + std::vector baseImages; + baseImages.reserve(metadata.depth); + for (size_t slice = 0; slice < metadata.depth; ++slice) + { + size_t index = metadata.ComputeIndex(0, 0, slice); + if (index >= nimages) + return E_FAIL; + + const Image& src = srcImages[index]; + if (!src.pixels) + return E_POINTER; + + if (src.format != metadata.format || src.width != metadata.width || src.height != metadata.height) + { + // All base images must be the same format, width, and height + return E_FAIL; + } + + baseImages.push_back(src); + } + + assert(baseImages.size() == metadata.depth); + + HRESULT hr; + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + DWORD filter_select = (filter & TEX_FILTER_MASK); + if (!filter_select) + { + // Default filter choice + filter_select = (ispow2(metadata.width) && ispow2(metadata.height) && ispow2(metadata.depth)) ? TEX_FILTER_BOX : TEX_FILTER_TRIANGLE; + } + + switch (filter_select) + { + case TEX_FILTER_BOX: + hr = Setup3DMips(&baseImages[0], metadata.depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsBoxFilter(metadata.depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_POINT: + hr = Setup3DMips(&baseImages[0], metadata.depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsPointFilter(metadata.depth, levels, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_LINEAR: + hr = Setup3DMips(&baseImages[0], metadata.depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsLinearFilter(metadata.depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_CUBIC: + hr = Setup3DMips(&baseImages[0], metadata.depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsCubicFilter(metadata.depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + case TEX_FILTER_TRIANGLE: + hr = Setup3DMips(&baseImages[0], metadata.depth, levels, mipChain); + if (FAILED(hr)) + return hr; + + hr = Generate3DMipsTriangleFilter(metadata.depth, levels, filter, mipChain); + if (FAILED(hr)) + mipChain.Release(); + return hr; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } +} diff --git a/Kits/DirectXTex/DirectXTexMisc.cpp b/Kits/DirectXTex/DirectXTexMisc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27683604b9496d82482ea7c6b615ce2bd1a24bff --- /dev/null +++ b/Kits/DirectXTex/DirectXTexMisc.cpp @@ -0,0 +1,765 @@ +//------------------------------------------------------------------------------------- +// DirectXTexMisc.cpp +// +// DirectX Texture Library - Misc image operations +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +using namespace DirectX; + +namespace +{ + const XMVECTORF32 g_Gamma22 = { { { 2.2f, 2.2f, 2.2f, 1.f } } }; + + //------------------------------------------------------------------------------------- + HRESULT ComputeMSE_( + const Image& image1, + const Image& image2, + float& mse, + _Out_writes_opt_(4) float* mseV, + DWORD flags) + { + if (!image1.pixels || !image2.pixels) + return E_POINTER; + + assert(image1.width == image2.width && image1.height == image2.height); + assert(!IsCompressed(image1.format) && !IsCompressed(image2.format)); + + const size_t width = image1.width; + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width) * 2, 16))); + if (!scanline) + return E_OUTOFMEMORY; + + // Flags implied from image formats + switch (image1.format) + { + case DXGI_FORMAT_B8G8R8X8_UNORM: + flags |= CMSE_IGNORE_ALPHA; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + flags |= CMSE_IMAGE1_SRGB | CMSE_IGNORE_ALPHA; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + flags |= CMSE_IMAGE1_SRGB; + break; + + default: + break; + } + + switch (image2.format) + { + case DXGI_FORMAT_B8G8R8X8_UNORM: + flags |= CMSE_IGNORE_ALPHA; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + flags |= CMSE_IMAGE2_SRGB | CMSE_IGNORE_ALPHA; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: + flags |= CMSE_IMAGE2_SRGB; + break; + + default: + break; + } + + const uint8_t *pSrc1 = image1.pixels; + const size_t rowPitch1 = image1.rowPitch; + + const uint8_t *pSrc2 = image2.pixels; + const size_t rowPitch2 = image2.rowPitch; + + XMVECTOR acc = g_XMZero; + static XMVECTORF32 two = { { { 2.0f, 2.0f, 2.0f, 2.0f } } }; + + for (size_t h = 0; h < image1.height; ++h) + { + XMVECTOR* ptr1 = scanline.get(); + if (!_LoadScanline(ptr1, width, pSrc1, rowPitch1, image1.format)) + return E_FAIL; + + XMVECTOR* ptr2 = scanline.get() + width; + if (!_LoadScanline(ptr2, width, pSrc2, rowPitch2, image2.format)) + return E_FAIL; + + for (size_t i = 0; i < width; ++i) + { + XMVECTOR v1 = *(ptr1++); + if (flags & CMSE_IMAGE1_SRGB) + { + v1 = XMVectorPow(v1, g_Gamma22); + } + if (flags & CMSE_IMAGE1_X2_BIAS) + { + v1 = XMVectorMultiplyAdd(v1, two, g_XMNegativeOne); + } + + XMVECTOR v2 = *(ptr2++); + if (flags & CMSE_IMAGE2_SRGB) + { + v2 = XMVectorPow(v2, g_Gamma22); + } + if (flags & CMSE_IMAGE2_X2_BIAS) + { + v2 = XMVectorMultiplyAdd(v2, two, g_XMNegativeOne); + } + + // sum[ (I1 - I2)^2 ] + XMVECTOR v = XMVectorSubtract(v1, v2); + if (flags & CMSE_IGNORE_RED) + { + v = XMVectorSelect(v, g_XMZero, g_XMMaskX); + } + if (flags & CMSE_IGNORE_GREEN) + { + v = XMVectorSelect(v, g_XMZero, g_XMMaskY); + } + if (flags & CMSE_IGNORE_BLUE) + { + v = XMVectorSelect(v, g_XMZero, g_XMMaskZ); + } + if (flags & CMSE_IGNORE_ALPHA) + { + v = XMVectorSelect(v, g_XMZero, g_XMMaskW); + } + + acc = XMVectorMultiplyAdd(v, v, acc); + } + + pSrc1 += rowPitch1; + pSrc2 += rowPitch2; + } + + // MSE = sum[ (I1 - I2)^2 ] / w*h + XMVECTOR d = XMVectorReplicate(float(image1.width * image1.height)); + XMVECTOR v = XMVectorDivide(acc, d); + if (mseV) + { + XMStoreFloat4(reinterpret_cast(mseV), v); + mse = mseV[0] + mseV[1] + mseV[2] + mseV[3]; + } + else + { + XMFLOAT4 _mseV; + XMStoreFloat4(&_mseV, v); + mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w; + } + + return S_OK; + } + + //------------------------------------------------------------------------------------- + HRESULT EvaluateImage_( + const Image& image, + std::function& pixelFunc) + { + if (!pixelFunc) + return E_INVALIDARG; + + if (!image.pixels) + return E_POINTER; + + assert(!IsCompressed(image.format)); + + const size_t width = image.width; + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + const uint8_t *pSrc = image.pixels; + const size_t rowPitch = image.rowPitch; + + for (size_t h = 0; h < image.height; ++h) + { + if (!_LoadScanline(scanline.get(), width, pSrc, rowPitch, image.format)) + return E_FAIL; + + pixelFunc(scanline.get(), width, h); + + pSrc += rowPitch; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + HRESULT TransformImage_( + const Image& srcImage, + std::function& pixelFunc, + const Image& destImage) + { + if (!pixelFunc) + return E_INVALIDARG; + + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + if (srcImage.width != destImage.width || srcImage.height != destImage.height || srcImage.format != destImage.format) + return E_FAIL; + + const size_t width = srcImage.width; + + ScopedAlignedArrayXMVECTOR scanlines(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width*2), 16))); + if (!scanlines) + return E_OUTOFMEMORY; + + XMVECTOR* sScanline = scanlines.get(); + XMVECTOR* dScanline = scanlines.get() + width; + + const uint8_t *pSrc = srcImage.pixels; + const size_t spitch = srcImage.rowPitch; + + uint8_t *pDest = destImage.pixels; + const size_t dpitch = destImage.rowPitch; + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(sScanline, width, pSrc, spitch, srcImage.format)) + return E_FAIL; + +#ifdef _DEBUG + memset(dScanline, 0xCD, sizeof(XMVECTOR)*width); +#endif + + pixelFunc(dScanline, sScanline, width, h); + + if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, dScanline, width)) + return E_FAIL; + + pSrc += spitch; + pDest += dpitch; + } + + return S_OK; + } +}; + + +//===================================================================================== +// Entry points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Copies a rectangle from one image into another +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CopyRectangle( + const Image& srcImage, + const Rect& srcRect, + const Image& dstImage, + DWORD filter, + size_t xOffset, + size_t yOffset) +{ + if (!srcImage.pixels || !dstImage.pixels) + return E_POINTER; + + if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format) + || IsPlanar(srcImage.format) || IsPlanar(dstImage.format) + || IsPalettized(srcImage.format) || IsPalettized(dstImage.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + // Validate rectangle/offset + if (!srcRect.w || !srcRect.h || ((srcRect.x + srcRect.w) > srcImage.width) || ((srcRect.y + srcRect.h) > srcImage.height)) + { + return E_INVALIDARG; + } + + if (((xOffset + srcRect.w) > dstImage.width) || ((yOffset + srcRect.h) > dstImage.height)) + { + return E_INVALIDARG; + } + + // Compute source bytes-per-pixel + size_t sbpp = BitsPerPixel(srcImage.format); + if (!sbpp) + return E_FAIL; + + if (sbpp < 8) + { + // We don't support monochrome (DXGI_FORMAT_R1_UNORM) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + const uint8_t* pEndSrc = srcImage.pixels + srcImage.rowPitch*srcImage.height; + const uint8_t* pEndDest = dstImage.pixels + dstImage.rowPitch*dstImage.height; + + // Round to bytes + sbpp = (sbpp + 7) / 8; + + const uint8_t* pSrc = srcImage.pixels + (srcRect.y * srcImage.rowPitch) + (srcRect.x * sbpp); + + if (srcImage.format == dstImage.format) + { + // Direct copy case (avoid intermediate conversions) + uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * sbpp); + const size_t copyW = srcRect.w * sbpp; + for (size_t h = 0; h < srcRect.h; ++h) + { + if (((pSrc + copyW) > pEndSrc) || (pDest > pEndDest)) + return E_FAIL; + + memcpy_s(pDest, pEndDest - pDest, pSrc, copyW); + + pSrc += srcImage.rowPitch; + pDest += dstImage.rowPitch; + } + + return S_OK; + } + + // Compute destination bytes-per-pixel (not the same format as source) + size_t dbpp = BitsPerPixel(dstImage.format); + if (!dbpp) + return E_FAIL; + + if (dbpp < 8) + { + // We don't support monochrome (DXGI_FORMAT_R1_UNORM) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Round to bytes + dbpp = (dbpp + 7) / 8; + + uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * dbpp); + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*srcRect.w), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + const size_t copyS = srcRect.w * sbpp; + const size_t copyD = srcRect.w * dbpp; + + for (size_t h = 0; h < srcRect.h; ++h) + { + if (((pSrc + copyS) > pEndSrc) || ((pDest + copyD) > pEndDest)) + return E_FAIL; + + if (!_LoadScanline(scanline.get(), srcRect.w, pSrc, copyS, srcImage.format)) + return E_FAIL; + + _ConvertScanline(scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter); + + if (!_StoreScanline(pDest, copyD, dstImage.format, scanline.get(), srcRect.w)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += dstImage.rowPitch; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Computes the Mean-Squared-Error (MSE) between two images +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::ComputeMSE( + const Image& image1, + const Image& image2, + float& mse, + float* mseV, + DWORD flags) +{ + if (!image1.pixels || !image2.pixels) + return E_POINTER; + + if (image1.width != image2.width || image1.height != image2.height) + return E_INVALIDARG; + + if (!IsValid(image1.format) || !IsValid(image2.format)) + return E_INVALIDARG; + + if (IsPlanar(image1.format) || IsPlanar(image2.format) + || IsPalettized(image1.format) || IsPalettized(image2.format) + || IsTypeless(image1.format) || IsTypeless(image2.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (IsCompressed(image1.format)) + { + if (IsCompressed(image2.format)) + { + // Case 1: both images are compressed, expand to RGBA32F + ScratchImage temp1; + HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1); + if (FAILED(hr)) + return hr; + + ScratchImage temp2; + hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2); + if (FAILED(hr)) + return hr; + + const Image* img1 = temp1.GetImage(0, 0, 0); + const Image* img2 = temp2.GetImage(0, 0, 0); + if (!img1 || !img2) + return E_POINTER; + + return ComputeMSE_(*img1, *img2, mse, mseV, flags); + } + else + { + // Case 2: image1 is compressed, expand to RGBA32F + ScratchImage temp; + HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp); + if (FAILED(hr)) + return hr; + + const Image* img = temp.GetImage(0, 0, 0); + if (!img) + return E_POINTER; + + return ComputeMSE_(*img, image2, mse, mseV, flags); + } + } + else + { + if (IsCompressed(image2.format)) + { + // Case 3: image2 is compressed, expand to RGBA32F + ScratchImage temp; + HRESULT hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp); + if (FAILED(hr)) + return hr; + + const Image* img = temp.GetImage(0, 0, 0); + if (!img) + return E_POINTER; + + return ComputeMSE_(image1, *img, mse, mseV, flags); + } + else + { + // Case 4: neither image is compressed + return ComputeMSE_(image1, image2, mse, mseV, flags); + } + } +} + + +//------------------------------------------------------------------------------------- +// Evaluates a user-supplied function for all the pixels in the image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::EvaluateImage( + const Image& image, + std::function pixelFunc) +{ + if (image.width > UINT32_MAX + || image.height > UINT32_MAX) + return E_INVALIDARG; + + if (!IsValid(image.format)) + return E_INVALIDARG; + + if (IsPlanar(image.format) || IsPalettized(image.format) || IsTypeless(image.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (IsCompressed(image.format)) + { + ScratchImage temp; + HRESULT hr = Decompress(image, DXGI_FORMAT_R32G32B32A32_FLOAT, temp); + if (FAILED(hr)) + return hr; + + const Image* img = temp.GetImage(0, 0, 0); + if (!img) + return E_POINTER; + + return EvaluateImage_(*img, pixelFunc); + } + else + { + return EvaluateImage_(image, pixelFunc); + } +} + +_Use_decl_annotations_ +HRESULT DirectX::EvaluateImage( + const Image* images, + size_t nimages, + const TexMetadata& metadata, + std::function pixelFunc) +{ + if (!images || !nimages) + return E_INVALIDARG; + + if (!IsValid(metadata.format)) + return E_INVALIDARG; + + if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || IsTypeless(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (metadata.width > UINT32_MAX + || metadata.height > UINT32_MAX) + return E_INVALIDARG; + + if (metadata.IsVolumemap() && metadata.depth > UINT16_MAX) + return E_INVALIDARG; + + ScratchImage temp; + DXGI_FORMAT format = metadata.format; + if (IsCompressed(format)) + { + HRESULT hr = Decompress(images, nimages, metadata, DXGI_FORMAT_R32G32B32A32_FLOAT, temp); + if (FAILED(hr)) + return hr; + + if (nimages != temp.GetImageCount()) + return E_UNEXPECTED; + + images = temp.GetImages(); + format = DXGI_FORMAT_R32G32B32A32_FLOAT; + } + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + for (size_t index = 0; index < nimages; ++index) + { + const Image& img = images[index]; + if (img.format != format) + return E_FAIL; + + if ((img.width > UINT32_MAX) || (img.height > UINT32_MAX)) + return E_FAIL; + + HRESULT hr = EvaluateImage_(img, pixelFunc); + if (FAILED(hr)) + return hr; + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + size_t index = 0; + size_t d = metadata.depth; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + for (size_t slice = 0; slice < d; ++slice, ++index) + { + if (index >= nimages) + return E_FAIL; + + const Image& img = images[index]; + if (img.format != format) + return E_FAIL; + + if ((img.width > UINT32_MAX) || (img.height > UINT32_MAX)) + return E_FAIL; + + HRESULT hr = EvaluateImage_(img, pixelFunc); + if (FAILED(hr)) + return hr; + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + return E_FAIL; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Use a user-supplied function to compute a new image from an input image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::TransformImage( + const Image& image, + std::function pixelFunc, + ScratchImage& result) +{ + if (image.width > UINT32_MAX + || image.height > UINT32_MAX) + return E_INVALIDARG; + + if (IsPlanar(image.format) || IsPalettized(image.format) || IsCompressed(image.format) || IsTypeless(image.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + HRESULT hr = result.Initialize2D(image.format, image.width, image.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image* dimg = result.GetImage(0, 0, 0); + if (!dimg) + { + result.Release(); + return E_POINTER; + } + + hr = TransformImage_(image, pixelFunc, *dimg); + if (FAILED(hr)) + { + result.Release(); + return hr; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::TransformImage( + const Image* srcImages, + size_t nimages, const TexMetadata& metadata, + std::function pixelFunc, + ScratchImage& result) +{ + if (!srcImages || !nimages) + return E_INVALIDARG; + + if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || IsCompressed(metadata.format) || IsTypeless(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (metadata.width > UINT32_MAX + || metadata.height > UINT32_MAX) + return E_INVALIDARG; + + if (metadata.IsVolumemap() && metadata.depth > UINT16_MAX) + return E_INVALIDARG; + + HRESULT hr = result.Initialize(metadata); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) + { + result.Release(); + return E_FAIL; + } + + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + for (size_t index = 0; index < nimages; ++index) + { + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + { + result.Release(); + return E_FAIL; + } + + const Image& dst = dest[index]; + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + hr = TransformImage_(src, pixelFunc, dst); + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + size_t index = 0; + size_t d = metadata.depth; + for (size_t level = 0; level < metadata.mipLevels; ++level) + { + for (size_t slice = 0; slice < d; ++slice, ++index) + { + if (index >= nimages) + { + result.Release(); + return E_FAIL; + } + + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + { + result.Release(); + return E_FAIL; + } + + const Image& dst = dest[index]; + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + hr = TransformImage_(src, pixelFunc, dst); + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + result.Release(); + return E_FAIL; + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexNormalMaps.cpp b/Kits/DirectXTex/DirectXTexNormalMaps.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be00499c346f8cee4b5e6aa681a5393262613bf0 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexNormalMaps.cpp @@ -0,0 +1,397 @@ +//------------------------------------------------------------------------------------- +// DirectXTexNormalMaps.cpp +// +// DirectX Texture Library - Normal map operations +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +using namespace DirectX; + +namespace +{ + +#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes") + inline float EvaluateColor(_In_ FXMVECTOR val, _In_ DWORD flags) + { + XMFLOAT4A f; + + static XMVECTORF32 lScale = { { { 0.2125f, 0.7154f, 0.0721f, 1.f } } }; + + static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask"); + switch (flags & 0xf) + { + case 0: + case CNMAP_CHANNEL_RED: return XMVectorGetX(val); + case CNMAP_CHANNEL_GREEN: return XMVectorGetY(val); + case CNMAP_CHANNEL_BLUE: return XMVectorGetZ(val); + case CNMAP_CHANNEL_ALPHA: return XMVectorGetW(val); + + case CNMAP_CHANNEL_LUMINANCE: + { + XMVECTOR v = XMVectorMultiply(val, lScale); + XMStoreFloat4A(&f, v); + return f.x + f.y + f.z; + } + break; + + default: + assert(false); + return 0.f; + } + } + + void EvaluateRow( + _In_reads_(width) const XMVECTOR* pSource, + _Out_writes_(width + 2) float* pDest, + size_t width, + DWORD flags) + { + assert(pSource && pDest); + assert(width > 0); + + for (size_t x = 0; x < width; ++x) + { + pDest[x + 1] = EvaluateColor(pSource[x], flags); + } + + if (flags & CNMAP_MIRROR_U) + { + // Mirror in U + pDest[0] = EvaluateColor(pSource[0], flags); + pDest[width + 1] = EvaluateColor(pSource[width - 1], flags); + } + else + { + // Wrap in U + pDest[0] = EvaluateColor(pSource[width - 1], flags); + pDest[width + 1] = EvaluateColor(pSource[0], flags); + } + } + + HRESULT ComputeNMap(_In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude, + _In_ DXGI_FORMAT format, _In_ const Image& normalMap) + { + if (!srcImage.pixels || !normalMap.pixels) + return E_INVALIDARG; + + const DWORD convFlags = _GetConvertFlags(format); + if (!convFlags) + return E_FAIL; + + if (!(convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT))) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + const size_t width = srcImage.width; + const size_t height = srcImage.height; + if (width != normalMap.width || height != normalMap.height) + return E_FAIL; + + // Allocate temporary space (4 scanlines and 3 evaluated rows) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*width * 4), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + ScopedAlignedArrayFloat buffer(reinterpret_cast(_aligned_malloc(((sizeof(float) * (width + 2)) * 3), 16))); + if (!buffer) + return E_OUTOFMEMORY; + + uint8_t* pDest = normalMap.pixels; + if (!pDest) + return E_POINTER; + + XMVECTOR* row0 = scanline.get(); + XMVECTOR* row1 = row0 + width; + XMVECTOR* row2 = row1 + width; + XMVECTOR* target = row2 + width; + + float* val0 = buffer.get(); + float* val1 = val0 + width + 2; + float* val2 = val1 + width + 2; + + const size_t rowPitch = srcImage.rowPitch; + const uint8_t* pSrc = srcImage.pixels; + + // Read first scanline row into 'row1' + if (!_LoadScanline(row1, width, pSrc, rowPitch, srcImage.format)) + return E_FAIL; + + // Setup 'row0' + if (flags & CNMAP_MIRROR_V) + { + // Mirror first row + memcpy_s(row0, rowPitch, row1, rowPitch); + } + else + { + // Read last row (Wrap V) + if (!_LoadScanline(row0, width, pSrc + (rowPitch * (height - 1)), rowPitch, srcImage.format)) + return E_FAIL; + } + + // Evaluate the initial rows + EvaluateRow(row0, val0, width, flags); + EvaluateRow(row1, val1, width, flags); + + pSrc += rowPitch; + + for (size_t y = 0; y < height; ++y) + { + // Load next scanline of source image + if (y < (height - 1)) + { + if (!_LoadScanline(row2, width, pSrc, rowPitch, srcImage.format)) + return E_FAIL; + } + else + { + if (flags & CNMAP_MIRROR_V) + { + // Use last row of source image + if (!_LoadScanline(row2, width, srcImage.pixels + (rowPitch * (height - 1)), rowPitch, srcImage.format)) + return E_FAIL; + } + else + { + // Use first row of source image (Wrap V) + if (!_LoadScanline(row2, width, srcImage.pixels, rowPitch, srcImage.format)) + return E_FAIL; + } + } + + // Evaluate row + EvaluateRow(row2, val2, width, flags); + + // Generate target scanline + XMVECTOR *dptr = target; + for (size_t x = 0; x < width; ++x) + { + // Compute normal via central differencing + float totDelta = (val0[x] - val0[x + 2]) + (val1[x] - val1[x + 2]) + (val2[x] - val2[x + 2]); + float deltaZX = totDelta * amplitude / 6.f; + + totDelta = (val0[x] - val2[x]) + (val0[x + 1] - val2[x + 1]) + (val0[x + 2] - val2[x + 2]); + float deltaZY = totDelta * amplitude / 6.f; + + XMVECTOR vx = XMVectorSetZ(g_XMNegIdentityR0, deltaZX); // (-1.0f, 0.0f, deltaZX) + XMVECTOR vy = XMVectorSetZ(g_XMNegIdentityR1, deltaZY); // (0.0f, -1.0f, deltaZY) + + XMVECTOR normal = XMVector3Normalize(XMVector3Cross(vx, vy)); + + // Compute alpha (1.0 or an occlusion term) + float alpha = 1.f; + + if (flags & CNMAP_COMPUTE_OCCLUSION) + { + float delta = 0.f; + float c = val1[x + 1]; + + float t = val0[x] - c; if (t > 0.f) delta += t; + t = val0[x + 1] - c; if (t > 0.f) delta += t; + t = val0[x + 2] - c; if (t > 0.f) delta += t; + t = val1[x] - c; if (t > 0.f) delta += t; + // Skip current pixel + t = val1[x + 2] - c; if (t > 0.f) delta += t; + t = val2[x] - c; if (t > 0.f) delta += t; + t = val2[x + 1] - c; if (t > 0.f) delta += t; + t = val2[x + 2] - c; if (t > 0.f) delta += t; + + // Average delta (divide by 8, scale by amplitude factor) + delta *= 0.125f * amplitude; + if (delta > 0.f) + { + // If < 0, then no occlusion + float r = sqrtf(1.f + delta*delta); + alpha = (r - delta) / r; + } + } + + // Encode based on target format + if (convFlags & CONVF_UNORM) + { + // 0.5f*normal + 0.5f -or- invert sign case: -0.5f*normal + 0.5f + XMVECTOR n1 = XMVectorMultiplyAdd((flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf); + *dptr++ = XMVectorSetW(n1, alpha); + } + else if (flags & CNMAP_INVERT_SIGN) + { + *dptr++ = XMVectorSetW(XMVectorNegate(normal), alpha); + } + else + { + *dptr++ = XMVectorSetW(normal, alpha); + } + } + + if (!_StoreScanline(pDest, normalMap.rowPitch, format, target, width)) + return E_FAIL; + + // Cycle buffers + float* temp = val0; + val0 = val1; + val1 = val2; + val2 = temp; + + pSrc += rowPitch; + pDest += normalMap.rowPitch; + } + + return S_OK; + } +} + + +//===================================================================================== +// Entry points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Generates a normal map from a height-map +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::ComputeNormalMap( + const Image& srcImage, + DWORD flags, + float amplitude, + DXGI_FORMAT format, + ScratchImage& normalMap) +{ + if (!srcImage.pixels || !IsValid(format)) + return E_INVALIDARG; + + static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask"); + switch (flags & 0xf) + { + case 0: + case CNMAP_CHANNEL_RED: + case CNMAP_CHANNEL_GREEN: + case CNMAP_CHANNEL_BLUE: + case CNMAP_CHANNEL_ALPHA: + case CNMAP_CHANNEL_LUMINANCE: + break; + + default: + return E_INVALIDARG; + } + + if (IsCompressed(format) || IsCompressed(srcImage.format) + || IsTypeless(format) || IsTypeless(srcImage.format) + || IsPlanar(format) || IsPlanar(srcImage.format) + || IsPalettized(format) || IsPalettized(srcImage.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + // Setup target image + normalMap.Release(); + + HRESULT hr = normalMap.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = normalMap.GetImage(0, 0, 0); + if (!img) + { + normalMap.Release(); + return E_POINTER; + } + + hr = ComputeNMap(srcImage, flags, amplitude, format, *img); + if (FAILED(hr)) + { + normalMap.Release(); + return hr; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::ComputeNormalMap( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DWORD flags, + float amplitude, + DXGI_FORMAT format, + ScratchImage& normalMaps) +{ + if (!srcImages || !nimages || !IsValid(format)) + return E_INVALIDARG; + + if (IsCompressed(format) || IsCompressed(metadata.format) + || IsTypeless(format) || IsTypeless(metadata.format) + || IsPlanar(format) || IsPlanar(metadata.format) + || IsPalettized(format) || IsPalettized(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask"); + switch (flags & 0xf) + { + case 0: + case CNMAP_CHANNEL_RED: + case CNMAP_CHANNEL_GREEN: + case CNMAP_CHANNEL_BLUE: + case CNMAP_CHANNEL_ALPHA: + case CNMAP_CHANNEL_LUMINANCE: + break; + + default: + return E_INVALIDARG; + } + + normalMaps.Release(); + + TexMetadata mdata2 = metadata; + mdata2.format = format; + HRESULT hr = normalMaps.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != normalMaps.GetImageCount()) + { + normalMaps.Release(); + return E_FAIL; + } + + const Image* dest = normalMaps.GetImages(); + if (!dest) + { + normalMaps.Release(); + return E_POINTER; + } + + for (size_t index = 0; index < nimages; ++index) + { + assert(dest[index].format == format); + + const Image& src = srcImages[index]; + if (IsCompressed(src.format) || IsTypeless(src.format)) + { + normalMaps.Release(); + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (src.width != dest[index].width || src.height != dest[index].height) + { + normalMaps.Release(); + return E_FAIL; + } + + hr = ComputeNMap(src, flags, amplitude, format, dest[index]); + if (FAILED(hr)) + { + normalMaps.Release(); + return hr; + } + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexPMAlpha.cpp b/Kits/DirectXTex/DirectXTexPMAlpha.cpp new file mode 100644 index 0000000000000000000000000000000000000000..233e667d010c18a11a150d17eef4bbe4b252cca6 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexPMAlpha.cpp @@ -0,0 +1,328 @@ +//------------------------------------------------------------------------------------- +// DirectXTexPMAlpha.cpp +// +// DirectX Texture Library - Premultiplied alpha operations +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +using namespace DirectX; + +namespace +{ + //--------------------------------------------------------------------------------- + // NonPremultiplied alpha -> Premultiplied alpha + HRESULT PremultiplyAlpha_(const Image& srcImage, const Image& destImage) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if (!pSrc || !pDest) + return E_POINTER; + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format)) + return E_FAIL; + + XMVECTOR* ptr = scanline.get(); + for (size_t w = 0; w < srcImage.width; ++w) + { + XMVECTOR v = *ptr; + XMVECTOR alpha = XMVectorSplatW(*ptr); + alpha = XMVectorMultiply(v, alpha); + *(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110); + } + + if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + + return S_OK; + } + + HRESULT PremultiplyAlphaLinear(const Image& srcImage, DWORD flags, const Image& destImage) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + static_assert(static_cast(TEX_PMALPHA_SRGB_IN) == static_cast(TEX_FILTER_SRGB_IN), "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_PMALPHA_SRGB_OUT) == static_cast(TEX_FILTER_SRGB_OUT), "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_PMALPHA_SRGB) == static_cast(TEX_FILTER_SRGB), "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*"); + flags &= TEX_PMALPHA_SRGB; + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if (!pSrc || !pDest) + return E_POINTER; + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanlineLinear(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags)) + return E_FAIL; + + XMVECTOR* ptr = scanline.get(); + for (size_t w = 0; w < srcImage.width; ++w) + { + XMVECTOR v = *ptr; + XMVECTOR alpha = XMVectorSplatW(*ptr); + alpha = XMVectorMultiply(v, alpha); + *(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110); + } + + if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + + return S_OK; + } + + //--------------------------------------------------------------------------------- + // Premultiplied alpha -> NonPremultiplied alpha (a.k.a. Straight alpha) + HRESULT DemultiplyAlpha(const Image& srcImage, const Image& destImage) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if (!pSrc || !pDest) + return E_POINTER; + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format)) + return E_FAIL; + + XMVECTOR* ptr = scanline.get(); + for (size_t w = 0; w < srcImage.width; ++w) + { + XMVECTOR v = *ptr; + XMVECTOR alpha = XMVectorSplatW(*ptr); + alpha = XMVectorDivide(v, alpha); + *(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110); + } + + if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + + return S_OK; + } + + HRESULT DemultiplyAlphaLinear(const Image& srcImage, DWORD flags, const Image& destImage) + { + assert(srcImage.width == destImage.width); + assert(srcImage.height == destImage.height); + + static_assert(static_cast(TEX_PMALPHA_SRGB_IN) == static_cast(TEX_FILTER_SRGB_IN), "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_PMALPHA_SRGB_OUT) == static_cast(TEX_FILTER_SRGB_OUT), "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*"); + static_assert(static_cast(TEX_PMALPHA_SRGB) == static_cast(TEX_FILTER_SRGB), "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*"); + flags &= TEX_PMALPHA_SRGB; + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if (!pSrc || !pDest) + return E_POINTER; + + for (size_t h = 0; h < srcImage.height; ++h) + { + if (!_LoadScanlineLinear(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags)) + return E_FAIL; + + XMVECTOR* ptr = scanline.get(); + for (size_t w = 0; w < srcImage.width; ++w) + { + XMVECTOR v = *ptr; + XMVECTOR alpha = XMVectorSplatW(*ptr); + alpha = XMVectorDivide(v, alpha); + *(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110); + } + + if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags)) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Converts to/from a premultiplied alpha version of the texture +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::PremultiplyAlpha( + const Image& srcImage, + DWORD flags, + ScratchImage& image) +{ + if (!srcImage.pixels) + return E_POINTER; + + if (IsCompressed(srcImage.format) + || IsPlanar(srcImage.format) + || IsPalettized(srcImage.format) + || IsTypeless(srcImage.format) + || !HasAlpha(srcImage.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) + return E_INVALIDARG; + + HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *rimage = image.GetImage(0, 0, 0); + if (!rimage) + { + image.Release(); + return E_POINTER; + } + + if (flags & TEX_PMALPHA_REVERSE) + { + hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? DemultiplyAlpha(srcImage, *rimage) : DemultiplyAlphaLinear(srcImage, flags, *rimage); + } + else + { + hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage); + } + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Converts to/from a premultiplied alpha version of the texture (complex) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::PremultiplyAlpha( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + DWORD flags, + ScratchImage& result) +{ + if (!srcImages || !nimages) + return E_INVALIDARG; + + if (IsCompressed(metadata.format) + || IsPlanar(metadata.format) + || IsPalettized(metadata.format) + || IsTypeless(metadata.format) + || !HasAlpha(metadata.format)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX)) + return E_INVALIDARG; + + if (metadata.IsPMAlpha() != ((flags & TEX_PMALPHA_REVERSE) != 0)) + return E_FAIL; + + TexMetadata mdata2 = metadata; + mdata2.SetAlphaMode((flags & TEX_PMALPHA_REVERSE) ? TEX_ALPHA_MODE_STRAIGHT : TEX_ALPHA_MODE_PREMULTIPLIED); + HRESULT hr = result.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + if (nimages != result.GetImageCount()) + { + result.Release(); + return E_FAIL; + } + + const Image* dest = result.GetImages(); + if (!dest) + { + result.Release(); + return E_POINTER; + } + + for (size_t index = 0; index < nimages; ++index) + { + const Image& src = srcImages[index]; + if (src.format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) + return E_FAIL; + + const Image& dst = dest[index]; + assert(dst.format == metadata.format); + + if (src.width != dst.width || src.height != dst.height) + { + result.Release(); + return E_FAIL; + } + + if (flags & TEX_PMALPHA_REVERSE) + { + hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? DemultiplyAlpha(src, dst) : DemultiplyAlphaLinear(src, flags, dst); + } + else + { + hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst); + } + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexResize.cpp b/Kits/DirectXTex/DirectXTexResize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49c723fbf21c952307e32c0cc838cf65554e63fa --- /dev/null +++ b/Kits/DirectXTex/DirectXTexResize.cpp @@ -0,0 +1,1061 @@ +//------------------------------------------------------------------------------------- +// DirectXTexResize.cpp +// +// DirectX Texture Library - Image resizing operations +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#include "filters.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace DirectX +{ + extern HRESULT _ResizeSeparateColorAndAlpha(_In_ IWICImagingFactory* pWIC, _In_ bool iswic2, _In_ IWICBitmap* original, + _In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img); +} + +namespace +{ + //--- Do image resize using WIC --- + HRESULT PerformResizeUsingWIC( + const Image& srcImage, + DWORD filter, + const WICPixelFormatGUID& pfGUID, + const Image& destImage) + { + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + assert(srcImage.format == destImage.format); + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr componentInfo; + HRESULT hr = pWIC->CreateComponentInfo(pfGUID, componentInfo.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr pixelFormatInfo; + hr = componentInfo.As(&pixelFormatInfo); + if (FAILED(hr)) + return hr; + + BOOL supportsTransparency = FALSE; + hr = pixelFormatInfo->SupportsTransparency(&supportsTransparency); + if (FAILED(hr)) + return hr; + + ComPtr source; + hr = pWIC->CreateBitmapFromMemory(static_cast(srcImage.width), static_cast(srcImage.height), pfGUID, + static_cast(srcImage.rowPitch), static_cast(srcImage.slicePitch), + srcImage.pixels, source.GetAddressOf()); + if (FAILED(hr)) + return hr; + + if ((filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency) + { + hr = _ResizeSeparateColorAndAlpha(pWIC, iswic2, source.Get(), destImage.width, destImage.height, filter, &destImage); + if (FAILED(hr)) + return hr; + } + else + { + ComPtr scaler; + hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(source.Get(), static_cast(destImage.width), static_cast(destImage.height), _GetWICInterp(filter)); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&pfScaler, &pfGUID, sizeof(WICPixelFormatGUID)) == 0) + { + hr = scaler->CopyPixels(0, static_cast(destImage.rowPitch), static_cast(destImage.slicePitch), destImage.pixels); + if (FAILED(hr)) + return hr; + } + else + { + // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we + // convert it back + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfScaler, pfGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(scaler.Get(), pfGUID, _GetWICDither(filter), nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(destImage.rowPitch), static_cast(destImage.slicePitch), destImage.pixels); + if (FAILED(hr)) + return hr; + } + } + + return S_OK; + } + + + //--- Do conversion, resize using WIC, conversion cycle --- + HRESULT PerformResizeViaF32( + const Image& srcImage, + DWORD filter, + const Image& destImage) + { + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + assert(srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT); + assert(srcImage.format == destImage.format); + + ScratchImage temp; + HRESULT hr = _ConvertToR32G32B32A32(srcImage, temp); + if (FAILED(hr)) + return hr; + + const Image *tsrc = temp.GetImage(0, 0, 0); + if (!tsrc) + return E_POINTER; + + ScratchImage rtemp; + hr = rtemp.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *tdest = rtemp.GetImage(0, 0, 0); + if (!tdest) + return E_POINTER; + + hr = PerformResizeUsingWIC(*tsrc, filter, GUID_WICPixelFormat128bppRGBAFloat, *tdest); + if (FAILED(hr)) + return hr; + + temp.Release(); + + hr = _ConvertFromR32G32B32A32(*tdest, destImage); + if (FAILED(hr)) + return hr; + + return S_OK; + } + + + //--- determine when to use WIC vs. non-WIC paths --- + bool UseWICFiltering(_In_ DXGI_FORMAT format, _In_ DWORD filter) + { + if (filter & TEX_FILTER_FORCE_NON_WIC) + { + // Explicit flag indicates use of non-WIC code paths + return false; + } + + if (filter & TEX_FILTER_FORCE_WIC) + { + // Explicit flag to use WIC code paths, skips all the case checks below + return true; + } + + if (IsSRGB(format) || (filter & TEX_FILTER_SRGB)) + { + // Use non-WIC code paths for sRGB correct filtering + return false; + } + +#if defined(_XBOX_ONE) && defined(_TITLE) + if (format == DXGI_FORMAT_R16G16B16A16_FLOAT + || format == DXGI_FORMAT_R16_FLOAT) + { + // Use non-WIC code paths as these conversions are not supported by Xbox One XDK + return false; + } +#endif + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + switch (filter & TEX_FILTER_MASK) + { + case TEX_FILTER_LINEAR: + if (filter & TEX_FILTER_WRAP) + { + // WIC only supports 'clamp' semantics (MIRROR is equivalent to clamp for linear) + return false; + } + + if (BitsPerColor(format) > 8) + { + // Avoid the WIC bitmap scaler when doing Linear filtering of XR/HDR formats + return false; + } + break; + + case TEX_FILTER_CUBIC: + if (filter & (TEX_FILTER_WRAP | TEX_FILTER_MIRROR)) + { + // WIC only supports 'clamp' semantics + return false; + } + + if (BitsPerColor(format) > 8) + { + // Avoid the WIC bitmap scaler when doing Cubic filtering of XR/HDR formats + return false; + } + break; + + case TEX_FILTER_TRIANGLE: + // WIC does not implement this filter + return false; + } + + return true; + } + + + //------------------------------------------------------------------------------------- + // Resize custom filters + //------------------------------------------------------------------------------------- + + //--- Point Filter --- + HRESULT ResizePointFilter(const Image& srcImage, const Image& destImage) + { + assert(srcImage.pixels && destImage.pixels); + assert(srcImage.format == destImage.format); + + // Allocate temporary space (2 scanlines) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc( + (sizeof(XMVECTOR) * (srcImage.width + destImage.width)), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row = target + destImage.width; + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR)*srcImage.width); +#endif + + const uint8_t* pSrc = srcImage.pixels; + uint8_t* pDest = destImage.pixels; + + size_t rowPitch = srcImage.rowPitch; + + size_t xinc = (srcImage.width << 16) / destImage.width; + size_t yinc = (srcImage.height << 16) / destImage.height; + + size_t lasty = size_t(-1); + + size_t sy = 0; + for (size_t y = 0; y < destImage.height; ++y) + { + if ((lasty ^ sy) >> 16) + { + if (!_LoadScanline(row, srcImage.width, pSrc + (rowPitch * (sy >> 16)), rowPitch, srcImage.format)) + return E_FAIL; + lasty = sy; + } + + size_t sx = 0; + for (size_t x = 0; x < destImage.width; ++x) + { + target[x] = row[sx >> 16]; + sx += xinc; + } + + if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, target, destImage.width)) + return E_FAIL; + pDest += destImage.rowPitch; + + sy += yinc; + } + + return S_OK; + } + + + //--- Box Filter --- + HRESULT ResizeBoxFilter(const Image& srcImage, DWORD filter, const Image& destImage) + { + assert(srcImage.pixels && destImage.pixels); + assert(srcImage.format == destImage.format); + + if (((destImage.width << 1) != srcImage.width) || ((destImage.height << 1) != srcImage.height)) + return E_FAIL; + + // Allocate temporary space (3 scanlines) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc( + (sizeof(XMVECTOR) * (srcImage.width * 2 + destImage.width)), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + XMVECTOR* target = scanline.get(); + + XMVECTOR* urow0 = target + destImage.width; + XMVECTOR* urow1 = urow0 + srcImage.width; + +#ifdef _DEBUG + memset(urow0, 0xCD, sizeof(XMVECTOR)*srcImage.width); + memset(urow1, 0xDD, sizeof(XMVECTOR)*srcImage.width); +#endif + + const XMVECTOR* urow2 = urow0 + 1; + const XMVECTOR* urow3 = urow1 + 1; + + const uint8_t* pSrc = srcImage.pixels; + uint8_t* pDest = destImage.pixels; + + size_t rowPitch = srcImage.rowPitch; + + for (size_t y = 0; y < destImage.height; ++y) + { + if (!_LoadScanlineLinear(urow0, srcImage.width, pSrc, rowPitch, srcImage.format, filter)) + return E_FAIL; + pSrc += rowPitch; + + if (urow0 != urow1) + { + if (!_LoadScanlineLinear(urow1, srcImage.width, pSrc, rowPitch, srcImage.format, filter)) + return E_FAIL; + pSrc += rowPitch; + } + + for (size_t x = 0; x < destImage.width; ++x) + { + size_t x2 = x << 1; + + AVERAGE4(target[x], urow0[x2], urow1[x2], urow2[x2], urow3[x2]); + } + + if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, target, destImage.width, filter)) + return E_FAIL; + pDest += destImage.rowPitch; + } + + return S_OK; + } + + + //--- Linear Filter --- + HRESULT ResizeLinearFilter(const Image& srcImage, DWORD filter, const Image& destImage) + { + assert(srcImage.pixels && destImage.pixels); + assert(srcImage.format == destImage.format); + + // Allocate temporary space (3 scanlines, plus X and Y filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc( + (sizeof(XMVECTOR) * (srcImage.width * 2 + destImage.width)), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr lf(new (std::nothrow) LinearFilter[destImage.width + destImage.height]); + if (!lf) + return E_OUTOFMEMORY; + + LinearFilter* lfX = lf.get(); + LinearFilter* lfY = lf.get() + destImage.width; + + _CreateLinearFilter(srcImage.width, destImage.width, (filter & TEX_FILTER_WRAP_U) != 0, lfX); + _CreateLinearFilter(srcImage.height, destImage.height, (filter & TEX_FILTER_WRAP_V) != 0, lfY); + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row0 = target + destImage.width; + XMVECTOR* row1 = row0 + srcImage.width; + +#ifdef _DEBUG + memset(row0, 0xCD, sizeof(XMVECTOR)*srcImage.width); + memset(row1, 0xDD, sizeof(XMVECTOR)*srcImage.width); +#endif + + const uint8_t* pSrc = srcImage.pixels; + uint8_t* pDest = destImage.pixels; + + size_t rowPitch = srcImage.rowPitch; + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + + for (size_t y = 0; y < destImage.height; ++y) + { + auto& toY = lfY[y]; + + if (toY.u0 != u0) + { + if (toY.u0 != u1) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(row0, srcImage.width, pSrc + (rowPitch * u0), rowPitch, srcImage.format, filter)) + return E_FAIL; + } + else + { + u0 = u1; + u1 = size_t(-1); + + std::swap(row0, row1); + } + } + + if (toY.u1 != u1) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(row1, srcImage.width, pSrc + (rowPitch * u1), rowPitch, srcImage.format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < destImage.width; ++x) + { + auto& toX = lfX[x]; + + BILINEAR_INTERPOLATE(target[x], toX, toY, row0, row1); + } + + if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, target, destImage.width, filter)) + return E_FAIL; + pDest += destImage.rowPitch; + } + + return S_OK; + } + + + //--- Cubic Filter --- + HRESULT ResizeCubicFilter(const Image& srcImage, DWORD filter, const Image& destImage) + { + assert(srcImage.pixels && destImage.pixels); + assert(srcImage.format == destImage.format); + + // Allocate temporary space (5 scanlines, plus X and Y filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc( + (sizeof(XMVECTOR) * (srcImage.width * 4 + destImage.width)), 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr cf(new (std::nothrow) CubicFilter[destImage.width + destImage.height]); + if (!cf) + return E_OUTOFMEMORY; + + CubicFilter* cfX = cf.get(); + CubicFilter* cfY = cf.get() + destImage.width; + + _CreateCubicFilter(srcImage.width, destImage.width, (filter & TEX_FILTER_WRAP_U) != 0, (filter & TEX_FILTER_MIRROR_U) != 0, cfX); + _CreateCubicFilter(srcImage.height, destImage.height, (filter & TEX_FILTER_WRAP_V) != 0, (filter & TEX_FILTER_MIRROR_V) != 0, cfY); + + XMVECTOR* target = scanline.get(); + + XMVECTOR* row0 = target + destImage.width; + XMVECTOR* row1 = row0 + srcImage.width; + XMVECTOR* row2 = row0 + srcImage.width * 2; + XMVECTOR* row3 = row0 + srcImage.width * 3; + +#ifdef _DEBUG + memset(row0, 0xCD, sizeof(XMVECTOR)*srcImage.width); + memset(row1, 0xDD, sizeof(XMVECTOR)*srcImage.width); + memset(row2, 0xED, sizeof(XMVECTOR)*srcImage.width); + memset(row3, 0xFD, sizeof(XMVECTOR)*srcImage.width); +#endif + + const uint8_t* pSrc = srcImage.pixels; + uint8_t* pDest = destImage.pixels; + + size_t rowPitch = srcImage.rowPitch; + + size_t u0 = size_t(-1); + size_t u1 = size_t(-1); + size_t u2 = size_t(-1); + size_t u3 = size_t(-1); + + for (size_t y = 0; y < destImage.height; ++y) + { + auto& toY = cfY[y]; + + // Scanline 1 + if (toY.u0 != u0) + { + if (toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3) + { + u0 = toY.u0; + + if (!_LoadScanlineLinear(row0, srcImage.width, pSrc + (rowPitch * u0), rowPitch, srcImage.format, filter)) + return E_FAIL; + } + else if (toY.u0 == u1) + { + u0 = u1; + u1 = size_t(-1); + + std::swap(row0, row1); + } + else if (toY.u0 == u2) + { + u0 = u2; + u2 = size_t(-1); + + std::swap(row0, row2); + } + else if (toY.u0 == u3) + { + u0 = u3; + u3 = size_t(-1); + + std::swap(row0, row3); + } + } + + // Scanline 2 + if (toY.u1 != u1) + { + if (toY.u1 != u2 && toY.u1 != u3) + { + u1 = toY.u1; + + if (!_LoadScanlineLinear(row1, srcImage.width, pSrc + (rowPitch * u1), rowPitch, srcImage.format, filter)) + return E_FAIL; + } + else if (toY.u1 == u2) + { + u1 = u2; + u2 = size_t(-1); + + std::swap(row1, row2); + } + else if (toY.u1 == u3) + { + u1 = u3; + u3 = size_t(-1); + + std::swap(row1, row3); + } + } + + // Scanline 3 + if (toY.u2 != u2) + { + if (toY.u2 != u3) + { + u2 = toY.u2; + + if (!_LoadScanlineLinear(row2, srcImage.width, pSrc + (rowPitch * u2), rowPitch, srcImage.format, filter)) + return E_FAIL; + } + else + { + u2 = u3; + u3 = size_t(-1); + + std::swap(row2, row3); + } + } + + // Scanline 4 + if (toY.u3 != u3) + { + u3 = toY.u3; + + if (!_LoadScanlineLinear(row3, srcImage.width, pSrc + (rowPitch * u3), rowPitch, srcImage.format, filter)) + return E_FAIL; + } + + for (size_t x = 0; x < destImage.width; ++x) + { + auto& toX = cfX[x]; + + XMVECTOR C0, C1, C2, C3; + + CUBIC_INTERPOLATE(C0, toX.x, row0[toX.u0], row0[toX.u1], row0[toX.u2], row0[toX.u3]); + CUBIC_INTERPOLATE(C1, toX.x, row1[toX.u0], row1[toX.u1], row1[toX.u2], row1[toX.u3]); + CUBIC_INTERPOLATE(C2, toX.x, row2[toX.u0], row2[toX.u1], row2[toX.u2], row2[toX.u3]); + CUBIC_INTERPOLATE(C3, toX.x, row3[toX.u0], row3[toX.u1], row3[toX.u2], row3[toX.u3]); + + CUBIC_INTERPOLATE(target[x], toY.x, C0, C1, C2, C3); + } + + if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, target, destImage.width, filter)) + return E_FAIL; + pDest += destImage.rowPitch; + } + + return S_OK; + } + + + //--- Triangle Filter --- + HRESULT ResizeTriangleFilter(const Image& srcImage, DWORD filter, const Image& destImage) + { + assert(srcImage.pixels && destImage.pixels); + assert(srcImage.format == destImage.format); + + using namespace TriangleFilter; + + // Allocate initial temporary space (1 scanline, accumulation rows, plus X and Y filters) + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * srcImage.width, 16))); + if (!scanline) + return E_OUTOFMEMORY; + + std::unique_ptr rowActive(new (std::nothrow) TriangleRow[destImage.height]); + if (!rowActive) + return E_OUTOFMEMORY; + + TriangleRow * rowFree = nullptr; + + std::unique_ptr tfX; + HRESULT hr = _Create(srcImage.width, destImage.width, (filter & TEX_FILTER_WRAP_U) != 0, tfX); + if (FAILED(hr)) + return hr; + + std::unique_ptr tfY; + hr = _Create(srcImage.height, destImage.height, (filter & TEX_FILTER_WRAP_V) != 0, tfY); + if (FAILED(hr)) + return hr; + + XMVECTOR* row = scanline.get(); + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR)*srcImage.width); +#endif + + auto xFromEnd = reinterpret_cast(reinterpret_cast(tfX.get()) + tfX->sizeInBytes); + auto yFromEnd = reinterpret_cast(reinterpret_cast(tfY.get()) + tfY->sizeInBytes); + + // Count times rows get written + for (FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; ) + { + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < destImage.height); + ++rowActive[v].remaining; + } + + yFrom = reinterpret_cast(reinterpret_cast(yFrom) + yFrom->sizeInBytes); + } + + // Filter image + const uint8_t* pSrc = srcImage.pixels; + size_t rowPitch = srcImage.rowPitch; + const uint8_t* pEndSrc = pSrc + rowPitch * srcImage.height; + + uint8_t* pDest = destImage.pixels; + + for (FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; ) + { + // Create accumulation rows as needed + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < destImage.height); + TriangleRow* rowAcc = &rowActive[v]; + + if (!rowAcc->scanline) + { + if (rowFree) + { + // Steal and reuse scanline from 'free row' list + assert(rowFree->scanline != 0); + rowAcc->scanline.reset(rowFree->scanline.release()); + rowFree = rowFree->next; + } + else + { + rowAcc->scanline.reset(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * destImage.width, 16))); + if (!rowAcc->scanline) + return E_OUTOFMEMORY; + } + + memset(rowAcc->scanline.get(), 0, sizeof(XMVECTOR) * destImage.width); + } + } + + // Load source scanline + if ((pSrc + rowPitch) > pEndSrc) + return E_FAIL; + + if (!_LoadScanlineLinear(row, srcImage.width, pSrc, rowPitch, srcImage.format, filter)) + return E_FAIL; + + pSrc += rowPitch; + + // Process row + size_t x = 0; + for (FilterFrom* xFrom = tfX->from; xFrom < xFromEnd; ++x) + { + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < destImage.height); + float yweight = yFrom->to[j].weight; + + XMVECTOR* accPtr = rowActive[v].scanline.get(); + if (!accPtr) + return E_POINTER; + + for (size_t k = 0; k < xFrom->count; ++k) + { + size_t u = xFrom->to[k].u; + assert(u < destImage.width); + + XMVECTOR weight = XMVectorReplicate(yweight * xFrom->to[k].weight); + + assert(x < srcImage.width); + accPtr[u] = XMVectorMultiplyAdd(row[x], weight, accPtr[u]); + } + } + + xFrom = reinterpret_cast(reinterpret_cast(xFrom) + xFrom->sizeInBytes); + } + + // Write completed accumulation rows + for (size_t j = 0; j < yFrom->count; ++j) + { + size_t v = yFrom->to[j].u; + assert(v < destImage.height); + TriangleRow* rowAcc = &rowActive[v]; + + assert(rowAcc->remaining > 0); + --rowAcc->remaining; + + if (!rowAcc->remaining) + { + XMVECTOR* pAccSrc = rowAcc->scanline.get(); + if (!pAccSrc) + return E_POINTER; + + switch (destImage.format) + { + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + { + // Need to slightly bias results for floating-point error accumulation which can + // be visible with harshly quantized values + static const XMVECTORF32 Bias = { { { 0.f, 0.f, 0.f, 0.1f } } }; + + XMVECTOR* ptr = pAccSrc; + for (size_t i = 0; i < destImage.width; ++i, ++ptr) + { + *ptr = XMVectorAdd(*ptr, Bias); + } + } + break; + + default: + break; + } + + // This performs any required clamping + if (!_StoreScanlineLinear(pDest + (destImage.rowPitch * v), destImage.rowPitch, destImage.format, pAccSrc, destImage.width, filter)) + return E_FAIL; + + // Put row on freelist to reuse it's allocated scanline + rowAcc->next = rowFree; + rowFree = rowAcc; + } + } + + yFrom = reinterpret_cast(reinterpret_cast(yFrom) + yFrom->sizeInBytes); + } + + return S_OK; + } + + + //--- Custom filter resize --- + HRESULT PerformResizeUsingCustomFilters(const Image& srcImage, DWORD filter, const Image& destImage) + { + if (!srcImage.pixels || !destImage.pixels) + return E_POINTER; + + static_assert(TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK"); + + DWORD filter_select = (filter & TEX_FILTER_MASK); + if (!filter_select) + { + // Default filter choice + filter_select = (((destImage.width << 1) == srcImage.width) && ((destImage.height << 1) == srcImage.height)) + ? TEX_FILTER_BOX : TEX_FILTER_LINEAR; + } + + switch (filter_select) + { + case TEX_FILTER_POINT: + return ResizePointFilter(srcImage, destImage); + + case TEX_FILTER_BOX: + return ResizeBoxFilter(srcImage, filter, destImage); + + case TEX_FILTER_LINEAR: + return ResizeLinearFilter(srcImage, filter, destImage); + + case TEX_FILTER_CUBIC: + return ResizeCubicFilter(srcImage, filter, destImage); + + case TEX_FILTER_TRIANGLE: + return ResizeTriangleFilter(srcImage, filter, destImage); + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Resize image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Resize( + const Image& srcImage, + size_t width, + size_t height, + DWORD filter, + ScratchImage& image) +{ + if (width == 0 || height == 0) + return E_INVALIDARG; + + if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) + return E_INVALIDARG; + + if ((width > UINT32_MAX) || (height > UINT32_MAX)) + return E_INVALIDARG; + + if (!srcImage.pixels) + return E_POINTER; + + if (IsCompressed(srcImage.format)) + { + // We don't support resizing compressed images + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + HRESULT hr = image.Initialize2D(srcImage.format, width, height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *rimage = image.GetImage(0, 0, 0); + if (!rimage) + return E_POINTER; + + if (UseWICFiltering(srcImage.format, filter)) + { + WICPixelFormatGUID pfGUID; + if (_DXGIToWIC(srcImage.format, pfGUID, true)) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = PerformResizeUsingWIC(srcImage, filter, pfGUID, *rimage); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back + hr = PerformResizeViaF32(srcImage, filter, *rimage); + } + } + else + { + hr = PerformResizeUsingCustomFilters(srcImage, filter, *rimage); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Resize image (complex) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::Resize( + const Image* srcImages, + size_t nimages, + const TexMetadata& metadata, + size_t width, + size_t height, + DWORD filter, + ScratchImage& result) +{ + if (!srcImages || !nimages || width == 0 || height == 0) + return E_INVALIDARG; + + if ((width > UINT32_MAX) || (height > UINT32_MAX)) + return E_INVALIDARG; + + TexMetadata mdata2 = metadata; + mdata2.width = width; + mdata2.height = height; + mdata2.mipLevels = 1; + HRESULT hr = result.Initialize(mdata2); + if (FAILED(hr)) + return hr; + + bool usewic = !metadata.IsPMAlpha() && UseWICFiltering(metadata.format, filter); + + WICPixelFormatGUID pfGUID = { 0 }; + bool wicpf = (usewic) ? _DXGIToWIC(metadata.format, pfGUID, true) : false; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + assert(metadata.depth == 1); + + for (size_t item = 0; item < metadata.arraySize; ++item) + { + size_t srcIndex = metadata.ComputeIndex(0, item, 0); + if (srcIndex >= nimages) + { + result.Release(); + return E_FAIL; + } + + const Image* srcimg = &srcImages[srcIndex]; + const Image* destimg = result.GetImage(0, item, 0); + if (!srcimg || !destimg) + { + result.Release(); + return E_POINTER; + } + + if (srcimg->format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((srcimg->width > UINT32_MAX) || (srcimg->height > UINT32_MAX)) + { + result.Release(); + return E_FAIL; + } + + if (usewic) + { + if (wicpf) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = PerformResizeUsingWIC(*srcimg, filter, pfGUID, *destimg); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back + hr = PerformResizeViaF32(*srcimg, filter, *destimg); + } + } + else + { + // Case 3: not using WIC resizing + hr = PerformResizeUsingCustomFilters(*srcimg, filter, *destimg); + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + assert(metadata.arraySize == 1); + + for (size_t slice = 0; slice < metadata.depth; ++slice) + { + size_t srcIndex = metadata.ComputeIndex(0, 0, slice); + if (srcIndex >= nimages) + { + result.Release(); + return E_FAIL; + } + + const Image* srcimg = &srcImages[srcIndex]; + const Image* destimg = result.GetImage(0, 0, slice); + if (!srcimg || !destimg) + { + result.Release(); + return E_POINTER; + } + + if (srcimg->format != metadata.format) + { + result.Release(); + return E_FAIL; + } + + if ((srcimg->width > UINT32_MAX) || (srcimg->height > UINT32_MAX)) + { + result.Release(); + return E_FAIL; + } + + if (usewic) + { + if (wicpf) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = PerformResizeUsingWIC(*srcimg, filter, pfGUID, *destimg); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back + hr = PerformResizeViaF32(*srcimg, filter, *destimg); + } + } + else + { + // Case 3: not using WIC resizing + hr = PerformResizeUsingCustomFilters(*srcimg, filter, *destimg); + } + + if (FAILED(hr)) + { + result.Release(); + return hr; + } + } + break; + + default: + result.Release(); + return E_FAIL; + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexTGA.cpp b/Kits/DirectXTex/DirectXTexTGA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13a644404e70181ef17a34bc829d09b8d7a599c7 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexTGA.cpp @@ -0,0 +1,1418 @@ +//------------------------------------------------------------------------------------- +// DirectXTexTGA.cpp +// +// DirectX Texture Library - Targa Truevision (TGA) file format reader/writer +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +// +// The implementation here has the following limitations: +// * Does not support files that contain color maps (these are rare in practice) +// * Interleaved files are not supported (deprecated aspect of TGA format) +// * Only supports 8-bit grayscale; 16-, 24-, and 32-bit truecolor images +// * Always writes uncompressed files (i.e. can read RLE compression, but does not write it) +// + +using namespace DirectX; + +namespace +{ + enum TGAImageType + { + TGA_NO_IMAGE = 0, + TGA_COLOR_MAPPED = 1, + TGA_TRUECOLOR = 2, + TGA_BLACK_AND_WHITE = 3, + TGA_COLOR_MAPPED_RLE = 9, + TGA_TRUECOLOR_RLE = 10, + TGA_BLACK_AND_WHITE_RLE = 11, + }; + + enum TGADescriptorFlags + { + TGA_FLAGS_INVERTX = 0x10, + TGA_FLAGS_INVERTY = 0x20, + TGA_FLAGS_INTERLEAVED_2WAY = 0x40, // Deprecated + TGA_FLAGS_INTERLEAVED_4WAY = 0x80, // Deprecated + }; + + const char* g_TGA20_Signature = "TRUEVISION-XFILE."; + +#pragma pack(push,1) + struct TGA_HEADER + { + uint8_t bIDLength; + uint8_t bColorMapType; + uint8_t bImageType; + uint16_t wColorMapFirst; + uint16_t wColorMapLength; + uint8_t bColorMapSize; + uint16_t wXOrigin; + uint16_t wYOrigin; + uint16_t wWidth; + uint16_t wHeight; + uint8_t bBitsPerPixel; + uint8_t bDescriptor; + }; + + struct TGA_FOOTER + { + uint16_t dwExtensionOffset; + uint16_t dwDeveloperOffset; + char Signature[18]; + }; + + struct TGA_EXTENSION + { + uint16_t wSize; + char szAuthorName[41]; + char szAuthorComment[324]; + uint16_t wStampMonth; + uint16_t wStampDay; + uint16_t wStampYear; + uint16_t wStampHour; + uint16_t wStampMinute; + uint16_t wStampSecond; + char szJobName[41]; + uint16_t wJobHour; + uint16_t wJobMinute; + uint16_t wJobSecond; + char szSoftwareId[41]; + uint16_t wVersionNumber; + uint8_t bVersionLetter; + uint32_t dwKeyColor; + uint16_t wPixelNumerator; + uint16_t wPixelDenominator; + uint16_t wGammaNumerator; + uint16_t wGammaDenominator; + uint32_t dwColorOffset; + uint32_t dwStampOffset; + uint32_t dwScanOffset; + uint8_t bAttributesType; + }; +#pragma pack(pop) + + enum CONVERSION_FLAGS + { + CONV_FLAGS_NONE = 0x0, + CONV_FLAGS_EXPAND = 0x1, // Conversion requires expanded pixel size + CONV_FLAGS_INVERTX = 0x2, // If set, scanlines are right-to-left + CONV_FLAGS_INVERTY = 0x4, // If set, scanlines are top-to-bottom + CONV_FLAGS_RLE = 0x8, // Source data is RLE compressed + + CONV_FLAGS_SWIZZLE = 0x10000, // Swizzle BGR<->RGB data + CONV_FLAGS_888 = 0x20000, // 24bpp format + }; + + + //------------------------------------------------------------------------------------- + // Decodes TGA header + //------------------------------------------------------------------------------------- + HRESULT DecodeTGAHeader( + _In_reads_bytes_(size) const void* pSource, + size_t size, + _Out_ TexMetadata& metadata, + size_t& offset, + _Inout_opt_ DWORD* convFlags) + { + if (!pSource) + return E_INVALIDARG; + + memset(&metadata, 0, sizeof(TexMetadata)); + + if (size < sizeof(TGA_HEADER)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + auto pHeader = reinterpret_cast(pSource); + + if (pHeader->bColorMapType != 0 + || pHeader->wColorMapLength != 0) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (pHeader->bDescriptor & (TGA_FLAGS_INTERLEAVED_2WAY | TGA_FLAGS_INTERLEAVED_4WAY)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (!pHeader->wWidth || !pHeader->wHeight) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + switch (pHeader->bImageType) + { + case TGA_TRUECOLOR: + case TGA_TRUECOLOR_RLE: + switch (pHeader->bBitsPerPixel) + { + case 16: + metadata.format = DXGI_FORMAT_B5G5R5A1_UNORM; + break; + + case 24: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + if (convFlags) + *convFlags |= CONV_FLAGS_EXPAND; + // We could use DXGI_FORMAT_B8G8R8X8_UNORM, but we prefer DXGI 1.0 formats + break; + + case 32: + metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + // We could use DXGI_FORMAT_B8G8R8A8_UNORM, but we prefer DXGI 1.0 formats + break; + } + + if (convFlags && (pHeader->bImageType == TGA_TRUECOLOR_RLE)) + { + *convFlags |= CONV_FLAGS_RLE; + } + break; + + case TGA_BLACK_AND_WHITE: + case TGA_BLACK_AND_WHITE_RLE: + switch (pHeader->bBitsPerPixel) + { + case 8: + metadata.format = DXGI_FORMAT_R8_UNORM; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (convFlags && (pHeader->bImageType == TGA_BLACK_AND_WHITE_RLE)) + { + *convFlags |= CONV_FLAGS_RLE; + } + break; + + case TGA_NO_IMAGE: + case TGA_COLOR_MAPPED: + case TGA_COLOR_MAPPED_RLE: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + default: + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + metadata.width = pHeader->wWidth; + metadata.height = pHeader->wHeight; + metadata.depth = metadata.arraySize = metadata.mipLevels = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + + if (convFlags) + { + if (pHeader->bDescriptor & TGA_FLAGS_INVERTX) + *convFlags |= CONV_FLAGS_INVERTX; + + if (pHeader->bDescriptor & TGA_FLAGS_INVERTY) + *convFlags |= CONV_FLAGS_INVERTY; + } + + offset = sizeof(TGA_HEADER); + + if (pHeader->bIDLength != 0) + { + offset += pHeader->bIDLength; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Set alpha for images with all 0 alpha channel + //------------------------------------------------------------------------------------- + HRESULT SetAlphaChannelToOpaque(_In_ const Image* image) + { + assert(image); + + auto pPixels = reinterpret_cast(image->pixels); + if (!pPixels) + return E_POINTER; + + for (size_t y = 0; y < image->height; ++y) + { + _CopyScanline(pPixels, image->rowPitch, pPixels, image->rowPitch, image->format, TEXP_SCANLINE_SETALPHA); + pPixels += image->rowPitch; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Uncompress pixel data from a TGA into the target image + //------------------------------------------------------------------------------------- + HRESULT UncompressPixels( + _In_reads_bytes_(size) const void* pSource, + size_t size, + _In_ const Image* image, + _In_ DWORD convFlags) + { + assert(pSource && size > 0); + + if (!image || !image->pixels) + return E_POINTER; + + // Compute TGA image data pitch + size_t rowPitch; + if (convFlags & CONV_FLAGS_EXPAND) + { + rowPitch = image->width * 3; + } + else + { + size_t slicePitch; + ComputePitch(image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE); + } + + auto sPtr = reinterpret_cast(pSource); + const uint8_t* endPtr = sPtr + size; + + switch (image->format) + { + //--------------------------------------------------------------------------- 8-bit + case DXGI_FORMAT_R8_UNORM: + for (size_t y = 0; y < image->height; ++y) + { + size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); + assert(offset < rowPitch); + + uint8_t* dPtr = reinterpret_cast(image->pixels) + + (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1))) + + offset; + + for (size_t x = 0; x < image->width; ) + { + if (sPtr >= endPtr) + return E_FAIL; + + if (*sPtr & 0x80) + { + // Repeat + size_t j = (*sPtr & 0x7F) + 1; + if (++sPtr >= endPtr) + return E_FAIL; + + for (; j > 0; --j, ++x) + { + if (x >= image->width) + return E_FAIL; + + *dPtr = *sPtr; + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + + ++sPtr; + } + else + { + // Literal + size_t j = (*sPtr & 0x7F) + 1; + ++sPtr; + + if (sPtr + j > endPtr) + return E_FAIL; + + for (; j > 0; --j, ++x) + { + if (x >= image->width) + return E_FAIL; + + *dPtr = *(sPtr++); + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + } + } + break; + + //-------------------------------------------------------------------------- 16-bit + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + bool nonzeroa = false; + for (size_t y = 0; y < image->height; ++y) + { + size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); + assert(offset * 2 < rowPitch); + + uint16_t* dPtr = reinterpret_cast(reinterpret_cast(image->pixels) + + (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1)))) + + offset; + + for (size_t x = 0; x < image->width; ) + { + if (sPtr >= endPtr) + return E_FAIL; + + if (*sPtr & 0x80) + { + // Repeat + size_t j = (*sPtr & 0x7F) + 1; + ++sPtr; + + if (sPtr + 1 >= endPtr) + return E_FAIL; + + uint16_t t = *sPtr | (*(sPtr + 1) << 8); + if (t & 0x8000) + nonzeroa = true; + sPtr += 2; + + for (; j > 0; --j, ++x) + { + if (x >= image->width) + return E_FAIL; + + *dPtr = t; + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + else + { + // Literal + size_t j = (*sPtr & 0x7F) + 1; + ++sPtr; + + if (sPtr + (j * 2) > endPtr) + return E_FAIL; + + for (; j > 0; --j, ++x) + { + if (x >= image->width) + return E_FAIL; + + uint16_t t = *sPtr | (*(sPtr + 1) << 8); + if (t & 0x8000) + nonzeroa = true; + sPtr += 2; + *dPtr = t; + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + } + } + + // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque + if (!nonzeroa) + { + HRESULT hr = SetAlphaChannelToOpaque(image); + if (FAILED(hr)) + return hr; + } + } + break; + + //----------------------------------------------------------------------- 24/32-bit + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + bool nonzeroa = false; + for (size_t y = 0; y < image->height; ++y) + { + size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); + + uint32_t* dPtr = reinterpret_cast(reinterpret_cast(image->pixels) + + (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1)))) + + offset; + + for (size_t x = 0; x < image->width; ) + { + if (sPtr >= endPtr) + return E_FAIL; + + if (*sPtr & 0x80) + { + // Repeat + size_t j = (*sPtr & 0x7F) + 1; + ++sPtr; + + DWORD t; + if (convFlags & CONV_FLAGS_EXPAND) + { + assert(offset * 3 < rowPitch); + + if (sPtr + 2 >= endPtr) + return E_FAIL; + + // BGR -> RGBA + t = (*sPtr << 16) | (*(sPtr + 1) << 8) | (*(sPtr + 2)) | 0xFF000000; + sPtr += 3; + + nonzeroa = true; + } + else + { + assert(offset * 4 < rowPitch); + + if (sPtr + 3 >= endPtr) + return E_FAIL; + + // BGRA -> RGBA + t = (*sPtr << 16) | (*(sPtr + 1) << 8) | (*(sPtr + 2)) | (*(sPtr + 3) << 24); + + if (*(sPtr + 3) > 0) + nonzeroa = true; + + sPtr += 4; + } + + for (; j > 0; --j, ++x) + { + if (x >= image->width) + return E_FAIL; + + *dPtr = t; + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + else + { + // Literal + size_t j = (*sPtr & 0x7F) + 1; + ++sPtr; + + if (convFlags & CONV_FLAGS_EXPAND) + { + if (sPtr + (j * 3) > endPtr) + return E_FAIL; + } + else + { + if (sPtr + (j * 4) > endPtr) + return E_FAIL; + } + + for (; j > 0; --j, ++x) + { + if (x >= image->width) + return E_FAIL; + + if (convFlags & CONV_FLAGS_EXPAND) + { + assert(offset * 3 < rowPitch); + + if (sPtr + 2 >= endPtr) + return E_FAIL; + + // BGR -> RGBA + *dPtr = (*sPtr << 16) | (*(sPtr + 1) << 8) | (*(sPtr + 2)) | 0xFF000000; + sPtr += 3; + + nonzeroa = true; + } + else + { + assert(offset * 4 < rowPitch); + + if (sPtr + 3 >= endPtr) + return E_FAIL; + + // BGRA -> RGBA + *dPtr = (*sPtr << 16) | (*(sPtr + 1) << 8) | (*(sPtr + 2)) | (*(sPtr + 3) << 24); + + if (*(sPtr + 3) > 0) + nonzeroa = true; + + sPtr += 4; + } + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + } + } + + // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque + if (!nonzeroa) + { + HRESULT hr = SetAlphaChannelToOpaque(image); + if (FAILED(hr)) + return hr; + } + } + break; + + //--------------------------------------------------------------------------------- + default: + return E_FAIL; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Copies pixel data from a TGA into the target image + //------------------------------------------------------------------------------------- + HRESULT CopyPixels( + _In_reads_bytes_(size) const void* pSource, + size_t size, + _In_ const Image* image, + _In_ DWORD convFlags) + { + assert(pSource && size > 0); + + if (!image || !image->pixels) + return E_POINTER; + + // Compute TGA image data pitch + size_t rowPitch; + if (convFlags & CONV_FLAGS_EXPAND) + { + rowPitch = image->width * 3; + } + else + { + size_t slicePitch; + ComputePitch(image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE); + } + + const uint8_t* sPtr = reinterpret_cast(pSource); + const uint8_t* endPtr = sPtr + size; + + switch (image->format) + { + //--------------------------------------------------------------------------- 8-bit + case DXGI_FORMAT_R8_UNORM: + for (size_t y = 0; y < image->height; ++y) + { + size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); + assert(offset < rowPitch); + + uint8_t* dPtr = reinterpret_cast(image->pixels) + + (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1))) + + offset; + + for (size_t x = 0; x < image->width; ++x) + { + if (sPtr >= endPtr) + return E_FAIL; + + *dPtr = *(sPtr++); + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + break; + + //-------------------------------------------------------------------------- 16-bit + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + bool nonzeroa = false; + for (size_t y = 0; y < image->height; ++y) + { + size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); + assert(offset * 2 < rowPitch); + + uint16_t* dPtr = reinterpret_cast(reinterpret_cast(image->pixels) + + (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1)))) + + offset; + + for (size_t x = 0; x < image->width; ++x) + { + if (sPtr + 1 >= endPtr) + return E_FAIL; + + uint16_t t = *sPtr | (*(sPtr + 1) << 8); + sPtr += 2; + *dPtr = t; + + if (t & 0x8000) + nonzeroa = true; + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + + // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque + if (!nonzeroa) + { + HRESULT hr = SetAlphaChannelToOpaque(image); + if (FAILED(hr)) + return hr; + } + } + break; + + //----------------------------------------------------------------------- 24/32-bit + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + bool nonzeroa = false; + for (size_t y = 0; y < image->height; ++y) + { + size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); + + uint32_t* dPtr = reinterpret_cast(reinterpret_cast(image->pixels) + + (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1)))) + + offset; + + for (size_t x = 0; x < image->width; ++x) + { + if (convFlags & CONV_FLAGS_EXPAND) + { + assert(offset * 3 < rowPitch); + + if (sPtr + 2 >= endPtr) + return E_FAIL; + + // BGR -> RGBA + *dPtr = (*sPtr << 16) | (*(sPtr + 1) << 8) | (*(sPtr + 2)) | 0xFF000000; + sPtr += 3; + + nonzeroa = true; + } + else + { + assert(offset * 4 < rowPitch); + + if (sPtr + 3 >= endPtr) + return E_FAIL; + + // BGRA -> RGBA + *dPtr = (*sPtr << 16) | (*(sPtr + 1) << 8) | (*(sPtr + 2)) | (*(sPtr + 3) << 24); + + if (*(sPtr + 3) > 0) + nonzeroa = true; + + sPtr += 4; + } + + if (convFlags & CONV_FLAGS_INVERTX) + --dPtr; + else + ++dPtr; + } + } + + // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque + if (!nonzeroa) + { + HRESULT hr = SetAlphaChannelToOpaque(image); + if (FAILED(hr)) + return hr; + } + } + break; + + //--------------------------------------------------------------------------------- + default: + return E_FAIL; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Encodes TGA file header + //------------------------------------------------------------------------------------- + HRESULT EncodeTGAHeader(_In_ const Image& image, _Out_ TGA_HEADER& header, _Inout_ DWORD& convFlags) + { + memset(&header, 0, sizeof(TGA_HEADER)); + + if ((image.width > 0xFFFF) + || (image.height > 0xFFFF)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + header.wWidth = static_cast(image.width); + header.wHeight = static_cast(image.height); + + switch (image.format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + header.bImageType = TGA_TRUECOLOR; + header.bBitsPerPixel = 32; + header.bDescriptor = TGA_FLAGS_INVERTY | 8; + convFlags |= CONV_FLAGS_SWIZZLE; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + header.bImageType = TGA_TRUECOLOR; + header.bBitsPerPixel = 32; + header.bDescriptor = TGA_FLAGS_INVERTY | 8; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + header.bImageType = TGA_TRUECOLOR; + header.bBitsPerPixel = 24; + header.bDescriptor = TGA_FLAGS_INVERTY; + convFlags |= CONV_FLAGS_888; + break; + + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_A8_UNORM: + header.bImageType = TGA_BLACK_AND_WHITE; + header.bBitsPerPixel = 8; + header.bDescriptor = TGA_FLAGS_INVERTY; + break; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + header.bImageType = TGA_TRUECOLOR; + header.bBitsPerPixel = 16; + header.bDescriptor = TGA_FLAGS_INVERTY | 1; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Copies BGRX data to form BGR 24bpp data + //------------------------------------------------------------------------------------- +#pragma warning(suppress: 6001 6101) // In the case where outSize is insufficient we do not write to pDestination + void Copy24bppScanline( + _Out_writes_bytes_(outSize) void* pDestination, + _In_ size_t outSize, + _In_reads_bytes_(inSize) const void* pSource, + _In_ size_t inSize) + { + assert(pDestination && outSize > 0); + assert(pSource && inSize > 0); + + assert(pDestination != pSource); + + const uint32_t * __restrict sPtr = reinterpret_cast(pSource); + uint8_t * __restrict dPtr = reinterpret_cast(pDestination); + + if (inSize >= 4 && outSize >= 3) + { + const uint8_t* endPtr = dPtr + outSize; + + for (size_t count = 0; count < (inSize - 3); count += 4) + { + uint32_t t = *(sPtr++); + + if (dPtr + 3 > endPtr) + return; + + *(dPtr++) = uint8_t(t & 0xFF); // Blue + *(dPtr++) = uint8_t((t & 0xFF00) >> 8); // Green + *(dPtr++) = uint8_t((t & 0xFF0000) >> 16); // Red + } + } + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Obtain metadata from TGA file in memory/on disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromTGAMemory( + const void* pSource, + size_t size, + TexMetadata& metadata ) +{ + if ( !pSource || size == 0 ) + return E_INVALIDARG; + + size_t offset; + return DecodeTGAHeader( pSource, size, metadata, offset, 0 ); +} + +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromTGAFile(const wchar_t* szFile, TexMetadata& metadata) +{ + if (!szFile) + return E_INVALIDARG; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid TGA file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the standard header to be a valid TGA + if (fileInfo.EndOfFile.LowPart < (sizeof(TGA_HEADER))) + { + return E_FAIL; + } + + // Read the standard header (we don't need the file footer to parse the file) + uint8_t header[sizeof(TGA_HEADER)]; + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, sizeof(TGA_HEADER), &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + size_t offset; + return DecodeTGAHeader(header, bytesRead, metadata, offset, 0); +} + + +//------------------------------------------------------------------------------------- +// Load a TGA file in memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromTGAMemory( + const void* pSource, + size_t size, + TexMetadata* metadata, + ScratchImage& image) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + image.Release(); + + size_t offset; + DWORD convFlags = 0; + TexMetadata mdata; + HRESULT hr = DecodeTGAHeader(pSource, size, mdata, offset, &convFlags); + if (FAILED(hr)) + return hr; + + if (offset > size) + return E_FAIL; + + auto pPixels = reinterpret_cast(reinterpret_cast(pSource) + offset); + + size_t remaining = size - offset; + if (remaining == 0) + return E_FAIL; + + hr = image.Initialize2D(mdata.format, mdata.width, mdata.height, 1, 1); + if (FAILED(hr)) + return hr; + + if (convFlags & CONV_FLAGS_RLE) + { + hr = UncompressPixels(pPixels, remaining, image.GetImage(0, 0, 0), convFlags); + } + else + { + hr = CopyPixels(pPixels, remaining, image.GetImage(0, 0, 0), convFlags); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Load a TGA file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromTGAFile( + const wchar_t* szFile, + TexMetadata* metadata, + ScratchImage& image) +{ + if (!szFile) + return E_INVALIDARG; + + image.Release(); + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid TGA file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the header to be a valid TGA + if (fileInfo.EndOfFile.LowPart < sizeof(TGA_HEADER)) + { + return E_FAIL; + } + + // Read the header + uint8_t header[sizeof(TGA_HEADER)]; + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, sizeof(TGA_HEADER), &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + size_t offset; + DWORD convFlags = 0; + TexMetadata mdata; + HRESULT hr = DecodeTGAHeader(header, bytesRead, mdata, offset, &convFlags); + if (FAILED(hr)) + return hr; + + // Read the pixels + DWORD remaining = static_cast(fileInfo.EndOfFile.LowPart - offset); + if (remaining == 0) + return E_FAIL; + + if (offset > sizeof(TGA_HEADER)) + { + // Skip past the id string + LARGE_INTEGER filePos = { { static_cast(offset), 0 } }; + if (!SetFilePointerEx(hFile.get(), filePos, 0, FILE_BEGIN)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + } + + hr = image.Initialize2D(mdata.format, mdata.width, mdata.height, 1, 1); + if (FAILED(hr)) + return hr; + + assert(image.GetPixels()); + + if (!(convFlags & (CONV_FLAGS_RLE | CONV_FLAGS_EXPAND | CONV_FLAGS_INVERTX)) && (convFlags & CONV_FLAGS_INVERTY)) + { + // This case we can read directly into the image buffer in place + if (!ReadFile(hFile.get(), image.GetPixels(), static_cast(image.GetPixelsSize()), &bytesRead, nullptr)) + { + image.Release(); + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesRead != image.GetPixelsSize()) + { + image.Release(); + return E_FAIL; + } + + switch (mdata.format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + // TGA stores 32-bit data in BGRA form, need to swizzle to RGBA + assert(image.GetImageCount() == 1); + const Image* img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + uint8_t *pPixels = img->pixels; + if (!pPixels) + { + image.Release(); + return E_POINTER; + } + + size_t rowPitch = img->rowPitch; + + // Scan for non-zero alpha channel + bool nonzeroa = false; + + for (size_t h = 0; h < img->height; ++h) + { + const uint32_t* sPtr = reinterpret_cast(pPixels); + + for (size_t x = 0; x < img->width; ++x) + { + if ((*sPtr) & 0xff000000) + { + nonzeroa = true; + break; + } + + ++sPtr; + } + + if (nonzeroa) + break; + + pPixels += rowPitch; + } + + DWORD tflags = (!nonzeroa) ? TEXP_SCANLINE_SETALPHA : TEXP_SCANLINE_NONE; + + // Swizzle scanlines + pPixels = img->pixels; + + for (size_t h = 0; h < img->height; ++h) + { + _SwizzleScanline(pPixels, rowPitch, pPixels, rowPitch, mdata.format, tflags); + pPixels += rowPitch; + } + } + break; + + // If we start using DXGI_FORMAT_B8G8R8X8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM we need to check for a fully 0 alpha channel + + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + assert(image.GetImageCount() == 1); + const Image* img = image.GetImage(0, 0, 0); + if (!img) + { + image.Release(); + return E_POINTER; + } + + // Scan for non-zero alpha channel + bool nonzeroa = false; + + const uint8_t *pPixels = img->pixels; + if (!pPixels) + { + image.Release(); + return E_POINTER; + } + + size_t rowPitch = img->rowPitch; + + for (size_t h = 0; h < img->height; ++h) + { + const uint16_t* sPtr = reinterpret_cast(pPixels); + + for (size_t x = 0; x < img->width; ++x) + { + if (*sPtr & 0x8000) + { + nonzeroa = true; + break; + } + + ++sPtr; + } + + if (nonzeroa) + break; + + pPixels += rowPitch; + } + + // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque + if (!nonzeroa) + { + hr = SetAlphaChannelToOpaque(img); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + } + } + break; + + default: + break; + } + } + else // RLE || EXPAND || INVERTX || !INVERTY + { + std::unique_ptr temp(new (std::nothrow) uint8_t[remaining]); + if (!temp) + { + image.Release(); + return E_OUTOFMEMORY; + } + + if (!ReadFile(hFile.get(), temp.get(), remaining, &bytesRead, nullptr)) + { + image.Release(); + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesRead != remaining) + { + image.Release(); + return E_FAIL; + } + + if (convFlags & CONV_FLAGS_RLE) + { + hr = UncompressPixels(temp.get(), remaining, image.GetImage(0, 0, 0), convFlags); + } + else + { + hr = CopyPixels(temp.get(), remaining, image.GetImage(0, 0, 0), convFlags); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a TGA file to memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToTGAMemory(const Image& image, Blob& blob) +{ + if (!image.pixels) + return E_POINTER; + + TGA_HEADER tga_header; + DWORD convFlags = 0; + HRESULT hr = EncodeTGAHeader(image, tga_header, convFlags); + if (FAILED(hr)) + return hr; + + blob.Release(); + + // Determine memory required for image data + size_t rowPitch, slicePitch; + if (convFlags & CONV_FLAGS_888) + { + rowPitch = image.width * 3; + slicePitch = image.height * rowPitch; + } + else + { + ComputePitch(image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE); + } + + hr = blob.Initialize(sizeof(TGA_HEADER) + slicePitch); + if (FAILED(hr)) + return hr; + + // Copy header + auto dPtr = reinterpret_cast(blob.GetBufferPointer()); + assert(dPtr != 0); + memcpy_s(dPtr, blob.GetBufferSize(), &tga_header, sizeof(TGA_HEADER)); + dPtr += sizeof(TGA_HEADER); + + auto pPixels = reinterpret_cast(image.pixels); + assert(pPixels); + + for (size_t y = 0; y < image.height; ++y) + { + // Copy pixels + if (convFlags & CONV_FLAGS_888) + { + Copy24bppScanline(dPtr, rowPitch, pPixels, image.rowPitch); + } + else if (convFlags & CONV_FLAGS_SWIZZLE) + { + _SwizzleScanline(dPtr, rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE); + } + else + { + _CopyScanline(dPtr, rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE); + } + + dPtr += rowPitch; + pPixels += image.rowPitch; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a TGA file to disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToTGAFile(const Image& image, const wchar_t* szFile) +{ + if (!szFile) + return E_INVALIDARG; + + if (!image.pixels) + return E_POINTER; + + TGA_HEADER tga_header; + DWORD convFlags = 0; + HRESULT hr = EncodeTGAHeader(image, tga_header, convFlags); + if (FAILED(hr)) + return hr; + + // Create file and write header +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + auto_delete_file delonfail(hFile.get()); + + // Determine size for TGA pixel data + size_t rowPitch, slicePitch; + if (convFlags & CONV_FLAGS_888) + { + rowPitch = image.width * 3; + slicePitch = image.height * rowPitch; + } + else + { + ComputePitch(image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE); + } + + if (slicePitch < 65535) + { + // For small images, it is better to create an in-memory file and write it out + Blob blob; + + hr = SaveToTGAMemory(image, blob); + if (FAILED(hr)) + return hr; + + // Write blob + const DWORD bytesToWrite = static_cast(blob.GetBufferSize()); + DWORD bytesWritten; + if (!WriteFile(hFile.get(), blob.GetBufferPointer(), bytesToWrite, &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != bytesToWrite) + { + return E_FAIL; + } + } + else + { + // Otherwise, write the image one scanline at a time... + std::unique_ptr temp(new (std::nothrow) uint8_t[rowPitch]); + if (!temp) + return E_OUTOFMEMORY; + + // Write header + DWORD bytesWritten; + if (!WriteFile(hFile.get(), &tga_header, sizeof(TGA_HEADER), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != sizeof(TGA_HEADER)) + return E_FAIL; + + // Write pixels + auto pPixels = reinterpret_cast(image.pixels); + + for (size_t y = 0; y < image.height; ++y) + { + // Copy pixels + if (convFlags & CONV_FLAGS_888) + { + Copy24bppScanline(temp.get(), rowPitch, pPixels, image.rowPitch); + } + else if (convFlags & CONV_FLAGS_SWIZZLE) + { + _SwizzleScanline(temp.get(), rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE); + } + else + { + _CopyScanline(temp.get(), rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE); + } + + pPixels += image.rowPitch; + + if (!WriteFile(hFile.get(), temp.get(), static_cast(rowPitch), &bytesWritten, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != rowPitch) + return E_FAIL; + } + } + + delonfail.clear(); + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexUtil.cpp b/Kits/DirectXTex/DirectXTexUtil.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96a238611988b888c1f6d6a3f8b929335b0e1cbd --- /dev/null +++ b/Kits/DirectXTex/DirectXTexUtil.cpp @@ -0,0 +1,1480 @@ +//------------------------------------------------------------------------------------- +// DirectXTexUtil.cpp +// +// DirectX Texture Library - Utilities +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +#if defined(_XBOX_ONE) && defined(_TITLE) +static_assert(XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT == DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT, "Xbox One XDK mismatch detected"); +static_assert(XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT == DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT, "Xbox One XDK mismatch detected"); +static_assert(XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT == DXGI_FORMAT_D16_UNORM_S8_UINT, "Xbox One XDK mismatch detected"); +static_assert(XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS == DXGI_FORMAT_R16_UNORM_X8_TYPELESS, "Xbox One XDK mismatch detected"); +static_assert(XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT == DXGI_FORMAT_X16_TYPELESS_G8_UINT, "Xbox One XDK mismatch detected"); +static_assert(XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM == DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM, "Xbox One XDK mismatch detected"); +static_assert(XBOX_DXGI_FORMAT_R4G4_UNORM == DXGI_FORMAT_R4G4_UNORM, "Xbox One XDK mismatch detected"); +#endif + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10) +static_assert(WIN10_DXGI_FORMAT_P208 == DXGI_FORMAT_P208, "Windows SDK mismatch detected"); +static_assert(WIN10_DXGI_FORMAT_V208 == DXGI_FORMAT_V208, "Windows SDK mismatch detected"); +static_assert(WIN10_DXGI_FORMAT_V408 == DXGI_FORMAT_V408, "Windows SDK mismatch detected"); +#endif + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + //------------------------------------------------------------------------------------- + // WIC Pixel Format Translation Data + //------------------------------------------------------------------------------------- + struct WICTranslate + { + GUID wic; + DXGI_FORMAT format; + bool srgb; + }; + + const WICTranslate g_WICFormats[] = + { + { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false }, + + { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false }, + { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true }, + + { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true }, + { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1 + { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1 + + { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1 + { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true }, + + { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true }, + { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true }, + + { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false }, + { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false }, + { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true }, + { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true }, + + { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false }, + + { GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false }, + }; + + bool g_WIC2 = false; + IWICImagingFactory* g_Factory = nullptr; +} + + +//===================================================================================== +// WIC Utilities +//===================================================================================== + +_Use_decl_annotations_ +DXGI_FORMAT DirectX::_WICToDXGI(const GUID& guid) +{ + for (size_t i = 0; i < _countof(g_WICFormats); ++i) + { + if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0) + return g_WICFormats[i].format; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + if (g_WIC2) + { + if (memcmp(&GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID)) == 0) + return DXGI_FORMAT_R32G32B32_FLOAT; + } +#endif + + return DXGI_FORMAT_UNKNOWN; +} + +_Use_decl_annotations_ +bool DirectX::_DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR ) +{ + switch( format ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + if ( ignoreRGBvsBGR ) + { + // If we are not doing conversion so don't really care about BGR vs RGB color-order, + // we can use the canonical WIC 32bppBGRA format which avoids an extra format conversion when using the WIC scaler + memcpy( &guid, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID) ); + } + else + { + memcpy( &guid, &GUID_WICPixelFormat32bppRGBA, sizeof(GUID) ); + } + return true; + + case DXGI_FORMAT_D32_FLOAT: + memcpy( &guid, &GUID_WICPixelFormat32bppGrayFloat, sizeof(GUID) ); + return true; + + case DXGI_FORMAT_D16_UNORM: + memcpy( &guid, &GUID_WICPixelFormat16bppGray, sizeof(GUID) ); + return true; + + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + memcpy( &guid, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID) ); + return true; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + memcpy( &guid, &GUID_WICPixelFormat32bppBGR, sizeof(GUID) ); + return true; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + case DXGI_FORMAT_R32G32B32_FLOAT: + if ( g_WIC2 ) + { + memcpy( &guid, &GUID_WICPixelFormat96bppRGBFloat, sizeof(GUID) ); + return true; + } + break; +#endif + + default: + for( size_t i=0; i < _countof(g_WICFormats); ++i ) + { + if ( g_WICFormats[i].format == format ) + { + memcpy( &guid, &g_WICFormats[i].wic, sizeof(GUID) ); + return true; + } + } + break; + } + + memcpy( &guid, &GUID_NULL, sizeof(GUID) ); + return false; +} + +DWORD DirectX::_CheckWICColorSpace(_In_ const GUID& sourceGUID, _In_ const GUID& targetGUID) +{ + DWORD srgb = 0; + + for (size_t i = 0; i < _countof(g_WICFormats); ++i) + { + if (memcmp(&g_WICFormats[i].wic, &sourceGUID, sizeof(GUID)) == 0) + { + if (g_WICFormats[i].srgb) + srgb |= TEX_FILTER_SRGB_IN; + } + + if (memcmp(&g_WICFormats[i].wic, &targetGUID, sizeof(GUID)) == 0) + { + if (g_WICFormats[i].srgb) + srgb |= TEX_FILTER_SRGB_OUT; + } + } + + if ((srgb & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) + { + srgb &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT); + } + + return srgb; +} + + +//------------------------------------------------------------------------------------- +// Public helper function to get common WIC codec GUIDs +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +REFGUID DirectX::GetWICCodec(WICCodecs codec) +{ + switch (codec) + { + case WIC_CODEC_BMP: + return GUID_ContainerFormatBmp; + + case WIC_CODEC_JPEG: + return GUID_ContainerFormatJpeg; + + case WIC_CODEC_PNG: + return GUID_ContainerFormatPng; + + case WIC_CODEC_TIFF: + return GUID_ContainerFormatTiff; + + case WIC_CODEC_GIF: + return GUID_ContainerFormatGif; + + case WIC_CODEC_WMP: + return GUID_ContainerFormatWmp; + + case WIC_CODEC_ICO: + return GUID_ContainerFormatIco; + + default: + return GUID_NULL; + } +} + + +//------------------------------------------------------------------------------------- +// Singleton function for WIC factory +//------------------------------------------------------------------------------------- +IWICImagingFactory* DirectX::GetWICFactory(bool& iswic2) +{ + if (g_Factory) + { + iswic2 = g_WIC2; + return g_Factory; + } + + static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT; + + InitOnceExecuteOnce(&s_initOnce, + [](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL + { +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory2), + factory + ); + + if (SUCCEEDED(hr)) + { + // WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed + g_WIC2 = true; + return TRUE; + } + else + { + g_WIC2 = false; + + hr = CoCreateInstance( + CLSID_WICImagingFactory1, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory), + factory + ); + return SUCCEEDED(hr) ? TRUE : FALSE; + } +#else + g_WIC2 = false; + + return SUCCEEDED(CoCreateInstance( + CLSID_WICImagingFactory, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory), + factory)) ? TRUE : FALSE; +#endif + }, nullptr, reinterpret_cast(&g_Factory)); + + iswic2 = g_WIC2; + return g_Factory; +} + + +//------------------------------------------------------------------------------------- +// Optional initializer for WIC factory +//------------------------------------------------------------------------------------- +void DirectX::SetWICFactory(_In_opt_ IWICImagingFactory* pWIC) +{ + if (pWIC == g_Factory) + return; + + bool iswic2 = false; + if (pWIC) + { +#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + ComPtr wic2; + HRESULT hr = pWIC->QueryInterface(IID_PPV_ARGS(wic2.GetAddressOf())); + if (SUCCEEDED(hr)) + { + iswic2 = true; + } +#endif + pWIC->AddRef(); + } + + g_WIC2 = iswic2; + std::swap(pWIC, g_Factory); + if (pWIC) + pWIC->Release(); +} + + + +//===================================================================================== +// DXGI Format Utilities +//===================================================================================== + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::IsPacked(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_YUY2: // 4:2:2 8-bit + case DXGI_FORMAT_Y210: // 4:2:2 10-bit + case DXGI_FORMAT_Y216: // 4:2:2 16-bit + return true; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::IsVideo(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + case DXGI_FORMAT_YUY2: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + case DXGI_FORMAT_NV11: + // These video formats can be used with the 3D pipeline through special view mappings + + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + // These are limited use video formats not usable in any way by the 3D pipeline + + case WIN10_DXGI_FORMAT_P208: + case WIN10_DXGI_FORMAT_V208: + case WIN10_DXGI_FORMAT_V408: + // These video formats are for JPEG Hardware decode (DXGI 1.4) + return true; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::IsPlanar(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_NV12: // 4:2:0 8-bit + case DXGI_FORMAT_P010: // 4:2:0 10-bit + case DXGI_FORMAT_P016: // 4:2:0 16-bit + case DXGI_FORMAT_420_OPAQUE:// 4:2:0 8-bit + case DXGI_FORMAT_NV11: // 4:1:1 8-bit + + case WIN10_DXGI_FORMAT_P208: // 4:2:2 8-bit + case WIN10_DXGI_FORMAT_V208: // 4:4:0 8-bit + case WIN10_DXGI_FORMAT_V408: // 4:4:4 8-bit + // These are JPEG Hardware decode formats (DXGI 1.4) + + case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + // These are Xbox One platform specific types + return true; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::IsDepthStencil(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_D32_FLOAT: + 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_D16_UNORM: + case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + return true; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::IsTypeless(DXGI_FORMAT fmt, bool partialTypeless) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC7_TYPELESS: + return true; + + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + return partialTypeless; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool DirectX::HasAlpha(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + 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_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + 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_A8_UNORM: + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + 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_B5G5R5A1_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_A8P8: + case DXGI_FORMAT_B4G4R4A4_UNORM: + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return true; + + default: + return false; + } +} + + +//------------------------------------------------------------------------------------- +// Returns bits-per-pixel for a given DXGI format, or 0 on failure +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +size_t DirectX::BitsPerPixel(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_YUY2: + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return 32; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + case WIN10_DXGI_FORMAT_V408: + return 24; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_A8P8: + case DXGI_FORMAT_B4G4R4A4_UNORM: + case WIN10_DXGI_FORMAT_P208: + case WIN10_DXGI_FORMAT_V208: + return 16; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_NV11: + return 12; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case XBOX_DXGI_FORMAT_R4G4_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; + } +} + + +//------------------------------------------------------------------------------------- +// Returns bits-per-color-channel for a given DXGI format, or 0 on failure +// For mixed formats, it returns the largest color-depth in the format +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +size_t DirectX::BitsPerColor(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + return 32; + + 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: + return 24; + + 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_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_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_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_P016: + case DXGI_FORMAT_Y216: + case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + return 16; + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return 14; + + case DXGI_FORMAT_R11G11B10_FLOAT: + return 11; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_Y210: + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return 10; + + 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_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_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_YUY2: + case DXGI_FORMAT_NV11: + case WIN10_DXGI_FORMAT_P208: + case WIN10_DXGI_FORMAT_V208: + case WIN10_DXGI_FORMAT_V408: + return 8; + + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 7; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + 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_B5G6R5_UNORM: + return 6; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + return 5; + + case DXGI_FORMAT_B4G4R4A4_UNORM: + case XBOX_DXGI_FORMAT_R4G4_UNORM: + return 4; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + // Palettized formats return 0 for this function + + default: + return 0; + } +} + + +//------------------------------------------------------------------------------------- +// Computes the image row pitch in bytes, and the slice ptich (size in bytes of the image) +// based on DXGI format, width, and height +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height, + size_t& rowPitch, size_t& slicePitch, DWORD flags) +{ + switch (static_cast(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: + assert(IsCompressed(fmt)); + { + if (flags & CP_FLAGS_BAD_DXTN_TAILS) + { + size_t nbw = width >> 2; + size_t nbh = height >> 2; + rowPitch = std::max(1, nbw * 8); + slicePitch = std::max(1, rowPitch * nbh); + } + else + { + size_t nbw = std::max(1, (width + 3) / 4); + size_t nbh = std::max(1, (height + 3) / 4); + rowPitch = nbw * 8; + slicePitch = rowPitch * nbh; + } + } + 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: + assert(IsCompressed(fmt)); + { + if (flags & CP_FLAGS_BAD_DXTN_TAILS) + { + size_t nbw = width >> 2; + size_t nbh = height >> 2; + rowPitch = std::max(1, nbw * 16); + slicePitch = std::max(1, rowPitch * nbh); + } + else + { + size_t nbw = std::max(1, (width + 3) / 4); + size_t nbh = std::max(1, (height + 3) / 4); + rowPitch = nbw * 16; + slicePitch = rowPitch * nbh; + } + } + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_YUY2: + assert(IsPacked(fmt)); + rowPitch = ((width + 1) >> 1) * 4; + slicePitch = rowPitch * height; + break; + + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + assert(IsPacked(fmt)); + rowPitch = ((width + 1) >> 1) * 8; + slicePitch = rowPitch * height; + break; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + assert(IsPlanar(fmt)); + rowPitch = ((width + 1) >> 1) * 2; + slicePitch = rowPitch * (height + ((height + 1) >> 1)); + break; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + assert(IsPlanar(fmt)); + rowPitch = ((width + 1) >> 1) * 4; + slicePitch = rowPitch * (height + ((height + 1) >> 1)); + break; + + case DXGI_FORMAT_NV11: + assert(IsPlanar(fmt)); + rowPitch = ((width + 3) >> 2) * 4; + slicePitch = rowPitch * height * 2; + break; + + case WIN10_DXGI_FORMAT_P208: + assert(IsPlanar(fmt)); + rowPitch = ((width + 1) >> 1) * 2; + slicePitch = rowPitch * height * 2; + break; + + case WIN10_DXGI_FORMAT_V208: + assert(IsPlanar(fmt)); + rowPitch = width; + slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2)); + break; + + case WIN10_DXGI_FORMAT_V408: + assert(IsPlanar(fmt)); + rowPitch = width; + slicePitch = rowPitch * (height + ((height >> 1) * 4)); + break; + + default: + assert(IsValid(fmt)); + assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt)); + { + + size_t bpp; + + if (flags & CP_FLAGS_24BPP) + bpp = 24; + else if (flags & CP_FLAGS_16BPP) + bpp = 16; + else if (flags & CP_FLAGS_8BPP) + bpp = 8; + else + bpp = BitsPerPixel(fmt); + + if (flags & (CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K)) + { + if (flags & CP_FLAGS_PAGE4K) + { + rowPitch = ((width * bpp + 32767) / 32768) * 4096; + slicePitch = rowPitch * height; + } + else if (flags & CP_FLAGS_ZMM) + { + rowPitch = ((width * bpp + 511) / 512) * 64; + slicePitch = rowPitch * height; + } + else if (flags & CP_FLAGS_YMM) + { + rowPitch = ((width * bpp + 255) / 256) * 32; + slicePitch = rowPitch * height; + } + else if (flags & CP_FLAGS_PARAGRAPH) + { + rowPitch = ((width * bpp + 127) / 128) * 16; + slicePitch = rowPitch * height; + } + else // DWORD alignment + { + // Special computation for some incorrectly created DDS files based on + // legacy DirectDraw assumptions about pitch alignment + rowPitch = ((width * bpp + 31) / 32) * sizeof(uint32_t); + slicePitch = rowPitch * height; + } + } + else + { + // Default byte alignment + rowPitch = (width * bpp + 7) / 8; + slicePitch = rowPitch * height; + } + } + break; + } +} + + +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +size_t DirectX::ComputeScanlines(DXGI_FORMAT fmt, size_t height) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + 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_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + 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: + assert(IsCompressed(fmt)); + return std::max(1, (height + 3) / 4); + + case DXGI_FORMAT_NV11: + case WIN10_DXGI_FORMAT_P208: + assert(IsPlanar(fmt)); + return height * 2; + + case WIN10_DXGI_FORMAT_V208: + assert(IsPlanar(fmt)); + return height + (((height + 1) >> 1) * 2); + + case WIN10_DXGI_FORMAT_V408: + assert(IsPlanar(fmt)); + return height + ((height >> 1) * 4); + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + case DXGI_FORMAT_420_OPAQUE: + case XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + assert(IsPlanar(fmt)); + return height + ((height + 1) >> 1); + + default: + assert(IsValid(fmt)); + assert(!IsCompressed(fmt) && !IsPlanar(fmt)); + return height; + } +} + + +//------------------------------------------------------------------------------------- +// Converts to an SRGB equivalent type if available +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +DXGI_FORMAT DirectX::MakeSRGB(DXGI_FORMAT fmt) +{ + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return fmt; + } +} + + +//------------------------------------------------------------------------------------- +// Converts to a format to an equivalent TYPELESS format if available +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +DXGI_FORMAT DirectX::MakeTypeless(DXGI_FORMAT fmt) +{ + switch (static_cast(fmt)) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return DXGI_FORMAT_R32G32B32A32_TYPELESS; + + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return DXGI_FORMAT_R32G32B32_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: + return DXGI_FORMAT_R16G16B16A16_TYPELESS; + + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + return DXGI_FORMAT_R32G32_TYPELESS; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return DXGI_FORMAT_R10G10B10A2_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: + return DXGI_FORMAT_R8G8B8A8_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: + return DXGI_FORMAT_R16G16_TYPELESS; + + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + return DXGI_FORMAT_R32_TYPELESS; + + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + return DXGI_FORMAT_R8G8_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: + return DXGI_FORMAT_R16_TYPELESS; + + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case XBOX_DXGI_FORMAT_R4G4_UNORM: + return DXGI_FORMAT_R8_TYPELESS; + + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + return DXGI_FORMAT_BC1_TYPELESS; + + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + return DXGI_FORMAT_BC2_TYPELESS; + + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + return DXGI_FORMAT_BC3_TYPELESS; + + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return DXGI_FORMAT_BC4_TYPELESS; + + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + return DXGI_FORMAT_BC5_TYPELESS; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_TYPELESS; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_TYPELESS; + + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + return DXGI_FORMAT_BC6H_TYPELESS; + + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return DXGI_FORMAT_BC7_TYPELESS; + + default: + return fmt; + } +} + + +//------------------------------------------------------------------------------------- +// Converts to a TYPELESS format to an equivalent UNORM format if available +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +DXGI_FORMAT DirectX::MakeTypelessUNORM(DXGI_FORMAT fmt) +{ + switch (fmt) + { + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return DXGI_FORMAT_R16G16B16A16_UNORM; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + return DXGI_FORMAT_R10G10B10A2_UNORM; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_R16G16_TYPELESS: + return DXGI_FORMAT_R16G16_UNORM; + + case DXGI_FORMAT_R8G8_TYPELESS: + return DXGI_FORMAT_R8G8_UNORM; + + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_UNORM; + + case DXGI_FORMAT_R8_TYPELESS: + return DXGI_FORMAT_R8_UNORM; + + case DXGI_FORMAT_BC1_TYPELESS: + return DXGI_FORMAT_BC1_UNORM; + + case DXGI_FORMAT_BC2_TYPELESS: + return DXGI_FORMAT_BC2_UNORM; + + case DXGI_FORMAT_BC3_TYPELESS: + return DXGI_FORMAT_BC3_UNORM; + + case DXGI_FORMAT_BC4_TYPELESS: + return DXGI_FORMAT_BC4_UNORM; + + case DXGI_FORMAT_BC5_TYPELESS: + return DXGI_FORMAT_BC5_UNORM; + + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return DXGI_FORMAT_B8G8R8X8_UNORM; + + case DXGI_FORMAT_BC7_TYPELESS: + return DXGI_FORMAT_BC7_UNORM; + + default: + return fmt; + } +} + + +//------------------------------------------------------------------------------------- +// Converts to a TYPELESS format to an equivalent FLOAT format if available +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +DXGI_FORMAT DirectX::MakeTypelessFLOAT(DXGI_FORMAT fmt) +{ + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + return DXGI_FORMAT_R32G32B32_FLOAT; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case DXGI_FORMAT_R32G32_TYPELESS: + return DXGI_FORMAT_R32G32_FLOAT; + + case DXGI_FORMAT_R16G16_TYPELESS: + return DXGI_FORMAT_R16G16_FLOAT; + + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_R32_FLOAT; + + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_FLOAT; + + default: + return fmt; + } +} + + +//===================================================================================== +// TexMetadata +//===================================================================================== + +_Use_decl_annotations_ +size_t TexMetadata::ComputeIndex(size_t mip, size_t item, size_t slice) const +{ + if (mip >= mipLevels) + return size_t(-1); + + switch (dimension) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + if (slice > 0) + return size_t(-1); + + if (item >= arraySize) + return size_t(-1); + + return (item*(mipLevels)+mip); + + case TEX_DIMENSION_TEXTURE3D: + if (item > 0) + { + // No support for arrays of volumes + return size_t(-1); + } + else + { + size_t index = 0; + size_t d = depth; + + for (size_t level = 0; level < mip; ++level) + { + index += d; + if (d > 1) + d >>= 1; + } + + if (slice >= d) + return size_t(-1); + + index += slice; + + return index; + } + break; + + default: + return size_t(-1); + } +} + + +//===================================================================================== +// Blob - Bitmap image container +//===================================================================================== + +Blob& Blob::operator= (Blob&& moveFrom) +{ + if (this != &moveFrom) + { + Release(); + + m_buffer = moveFrom.m_buffer; + m_size = moveFrom.m_size; + + moveFrom.m_buffer = nullptr; + moveFrom.m_size = 0; + } + return *this; +} + +void Blob::Release() +{ + if (m_buffer) + { + _aligned_free(m_buffer); + m_buffer = nullptr; + } + + m_size = 0; +} + +_Use_decl_annotations_ +HRESULT Blob::Initialize(size_t size) +{ + if (!size) + return E_INVALIDARG; + + Release(); + + m_buffer = _aligned_malloc(size, 16); + if (!m_buffer) + { + Release(); + return E_OUTOFMEMORY; + } + + m_size = size; + + return S_OK; +} + +HRESULT Blob::Trim(size_t size) +{ + if (!size) + return E_INVALIDARG; + + if (!m_buffer) + return E_UNEXPECTED; + + if (size > m_size) + return E_INVALIDARG; + + m_size = size; + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexWIC.cpp b/Kits/DirectXTex/DirectXTexWIC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3132bafa64faca035efaff2c2666f5567ca81e5f --- /dev/null +++ b/Kits/DirectXTex/DirectXTexWIC.cpp @@ -0,0 +1,1330 @@ +//------------------------------------------------------------------------------------- +// DirectXTexWIC.cpp +// +// DirectX Texture Library - WIC-based file reader/writer +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" + +//------------------------------------------------------------------------------------- +// IStream support for WIC Memory routines +//------------------------------------------------------------------------------------- + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + + #include + #pragma comment(lib,"shcore.lib") + +#ifdef __cplusplus_winrt + + static inline HRESULT CreateMemoryStream( _Outptr_ IStream** stream ) + { + auto randomAccessStream = ref new ::Windows::Storage::Streams::InMemoryRandomAccessStream(); + return CreateStreamOverRandomAccessStream( randomAccessStream, IID_PPV_ARGS( stream ) ); + } + +#else + +#pragma warning(push) +#pragma warning(disable : 4619 5038) + #include + #include +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4471) + #include +#pragma warning(pop) + + static inline HRESULT CreateMemoryStream( _Outptr_ IStream** stream ) + { + Microsoft::WRL::ComPtr abiStream; + HRESULT hr = Windows::Foundation::ActivateInstance( + Microsoft::WRL::Wrappers::HStringReference( RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream ).Get(), + abiStream.GetAddressOf() ); + + if (SUCCEEDED(hr)) + { + hr = CreateStreamOverRandomAccessStream( abiStream.Get(), IID_PPV_ARGS( stream ) ); + } + return hr; + } + +#endif // __cplusplus_winrt + +#else + + #pragma prefast(suppress:6387 28196, "a simple wrapper around an existing annotated function" ); + static inline HRESULT CreateMemoryStream( _Outptr_ IStream** stream ) + { + return CreateStreamOnHGlobal( 0, TRUE, stream ); + } + +#endif + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + + //------------------------------------------------------------------------------------- + // WIC Pixel Format nearest conversion table + //------------------------------------------------------------------------------------- + + struct WICConvert + { + GUID source; + GUID target; + }; + + const WICConvert g_WICConvert[] = + { + // Directly support the formats listed in XnaTexUtil::g_WICFormats, so no conversion required + // Note target GUID in this conversion table must be one of those directly supported formats. + + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT + + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM + + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + #endif + + // We don't support n-channel formats + }; + + //------------------------------------------------------------------------------------- + // Returns the DXGI format and optionally the WIC pixel GUID to convert to + //------------------------------------------------------------------------------------- + DXGI_FORMAT DetermineFormat( + _In_ const WICPixelFormatGUID& pixelFormat, + DWORD flags, + bool iswic2, + _Out_opt_ WICPixelFormatGUID* pConvert) + { + if (pConvert) + memset(pConvert, 0, sizeof(WICPixelFormatGUID)); + + DXGI_FORMAT format = _WICToDXGI(pixelFormat); + + if (format == DXGI_FORMAT_UNKNOWN) + { + if (memcmp(&GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + if (iswic2) + { + if (pConvert) + memcpy(pConvert, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID)); + format = DXGI_FORMAT_R32G32B32_FLOAT; + } + else +#else + UNREFERENCED_PARAMETER(iswic2); +#endif + { + if (pConvert) + memcpy(pConvert, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID)); + format = DXGI_FORMAT_R32G32B32A32_FLOAT; + } + } + else + { + for (size_t i = 0; i < _countof(g_WICConvert); ++i) + { + if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { + if (pConvert) + memcpy(pConvert, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID)); + + format = _WICToDXGI(g_WICConvert[i].target); + assert(format != DXGI_FORMAT_UNKNOWN); + break; + } + } + } + } + + // Handle special cases based on flags + switch (format) + { + case DXGI_FORMAT_B8G8R8A8_UNORM: // BGRA + case DXGI_FORMAT_B8G8R8X8_UNORM: // BGRX + if (flags & WIC_FLAGS_FORCE_RGB) + { + format = DXGI_FORMAT_R8G8B8A8_UNORM; + if (pConvert) + memcpy(pConvert, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID)); + } + break; + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + if (flags & WIC_FLAGS_NO_X2_BIAS) + { + format = DXGI_FORMAT_R10G10B10A2_UNORM; + if (pConvert) + memcpy(pConvert, &GUID_WICPixelFormat32bppRGBA1010102, sizeof(WICPixelFormatGUID)); + } + break; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + if (flags & WIC_FLAGS_NO_16BPP) + { + format = DXGI_FORMAT_R8G8B8A8_UNORM; + if (pConvert) + memcpy(pConvert, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID)); + } + break; + + case DXGI_FORMAT_R1_UNORM: + if (!(flags & WIC_FLAGS_ALLOW_MONO)) + { + // By default we want to promote a black & white to gresycale since R1 is not a generally supported D3D format + format = DXGI_FORMAT_R8_UNORM; + if (pConvert) + memcpy(pConvert, &GUID_WICPixelFormat8bppGray, sizeof(WICPixelFormatGUID)); + } + break; + + default: + break; + } + + return format; + } + + + //------------------------------------------------------------------------------------- + // Determines metadata for image + //------------------------------------------------------------------------------------- + HRESULT DecodeMetadata( + DWORD flags, + bool iswic2, + _In_ IWICBitmapDecoder *decoder, + _In_ IWICBitmapFrameDecode *frame, + _Out_ TexMetadata& metadata, + _Out_opt_ WICPixelFormatGUID* pConvert, + _In_opt_ std::function getMQR) + { + if (!decoder || !frame) + return E_POINTER; + + memset(&metadata, 0, sizeof(TexMetadata)); + metadata.depth = 1; + metadata.mipLevels = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + + UINT w, h; + HRESULT hr = frame->GetSize(&w, &h); + if (FAILED(hr)) + return hr; + + metadata.width = w; + metadata.height = h; + + if (flags & WIC_FLAGS_ALL_FRAMES) + { + UINT fcount; + hr = decoder->GetFrameCount(&fcount); + if (FAILED(hr)) + return hr; + + metadata.arraySize = fcount; + } + else + metadata.arraySize = 1; + + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat(&pixelFormat); + if (FAILED(hr)) + return hr; + + metadata.format = DetermineFormat(pixelFormat, flags, iswic2, pConvert); + if (metadata.format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (!(flags & WIC_FLAGS_IGNORE_SRGB)) + { + GUID containerFormat; + hr = decoder->GetContainerFormat(&containerFormat); + if (FAILED(hr)) + return hr; + + ComPtr metareader; + hr = frame->GetMetadataQueryReader(metareader.GetAddressOf()); + if (SUCCEEDED(hr)) + { + // Check for sRGB colorspace metadata + bool sRGB = false; + + PROPVARIANT value; + PropVariantInit(&value); + + if (memcmp(&containerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0) + { + // Check for sRGB chunk + if (SUCCEEDED(metareader->GetMetadataByName(L"/sRGB/RenderingIntent", &value)) && value.vt == VT_UI1) + { + sRGB = true; + } + } +#if defined(_XBOX_ONE) && defined(_TITLE) + else if (memcmp(&containerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID)) == 0) + { + if (SUCCEEDED(metareader->GetMetadataByName(L"/app1/ifd/exif/{ushort=40961}", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } + } + else if (memcmp(&containerFormat, &GUID_ContainerFormatTiff, sizeof(GUID)) == 0) + { + if (SUCCEEDED(metareader->GetMetadataByName(L"/ifd/exif/{ushort=40961}", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } + } +#else + else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } +#endif + + (void)PropVariantClear(&value); + + if (sRGB) + metadata.format = MakeSRGB(metadata.format); + } + else if (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) + { + // Some formats just don't support metadata (BMP, ICO, etc.), so ignore this failure + hr = S_OK; + } + } + + if (getMQR) + { + ComPtr metareader; + if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf()))) + { + getMQR(metareader.Get()); + } + } + + return hr; + } + + + //------------------------------------------------------------------------------------- + // Decodes a single frame + //------------------------------------------------------------------------------------- + HRESULT DecodeSingleFrame( + DWORD flags, + const TexMetadata& metadata, + const WICPixelFormatGUID& convertGUID, + _In_ IWICBitmapFrameDecode *frame, + _Inout_ ScratchImage& image) + { + if (!frame) + return E_POINTER; + + HRESULT hr = image.Initialize2D(metadata.format, metadata.width, metadata.height, 1, 1); + if (FAILED(hr)) + return hr; + + const Image *img = image.GetImage(0, 0, 0); + if (!img) + return E_POINTER; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + if (memcmp(&convertGUID, &GUID_NULL, sizeof(GUID)) == 0) + { + hr = frame->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + else + { + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat(&pixelFormat); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(frame, convertGUID, _GetWICDither(flags), nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Decodes an image array, resizing/format converting as needed + //------------------------------------------------------------------------------------- + HRESULT DecodeMultiframe( + DWORD flags, + const TexMetadata& metadata, + _In_ IWICBitmapDecoder *decoder, + _Inout_ ScratchImage& image) + { + if (!decoder) + return E_POINTER; + + HRESULT hr = image.Initialize2D(metadata.format, metadata.width, metadata.height, metadata.arraySize, 1); + if (FAILED(hr)) + return hr; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + WICPixelFormatGUID sourceGUID; + if (!_DXGIToWIC(metadata.format, sourceGUID)) + return E_FAIL; + + for (size_t index = 0; index < metadata.arraySize; ++index) + { + const Image* img = image.GetImage(0, index, 0); + if (!img) + return E_POINTER; + + ComPtr frame; + hr = decoder->GetFrame(static_cast(index), frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfGuid; + hr = frame->GetPixelFormat(&pfGuid); + if (FAILED(hr)) + return hr; + + UINT w, h; + hr = frame->GetSize(&w, &h); + if (FAILED(hr)) + return hr; + + if (w == metadata.width && h == metadata.height) + { + // This frame does not need resized + if (memcmp(&pfGuid, &sourceGUID, sizeof(WICPixelFormatGUID)) == 0) + { + hr = frame->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + else + { + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfGuid, sourceGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(frame.Get(), sourceGUID, _GetWICDither(flags), nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + } + else + { + // This frame needs resizing + ComPtr scaler; + hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(frame.Get(), static_cast(metadata.width), static_cast(metadata.height), _GetWICInterp(flags)); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&pfScaler, &sourceGUID, sizeof(WICPixelFormatGUID)) == 0) + { + hr = scaler->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + else + { + // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we + // convert it to our desired format + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfScaler, sourceGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(scaler.Get(), sourceGUID, _GetWICDither(flags), nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(img->rowPitch), static_cast(img->slicePitch), img->pixels); + if (FAILED(hr)) + return hr; + } + } + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Encodes image metadata + //------------------------------------------------------------------------------------- + HRESULT EncodeMetadata( + _In_ IWICBitmapFrameEncode* frame, + const GUID& containerFormat, + DXGI_FORMAT format) + { + if (!frame) + return E_POINTER; + + ComPtr metawriter; + HRESULT hr = frame->GetMetadataQueryWriter(metawriter.GetAddressOf()); + if (SUCCEEDED(hr)) + { + PROPVARIANT value; + PropVariantInit(&value); + + bool sRGB = IsSRGB(format); + + value.vt = VT_LPSTR; + value.pszVal = const_cast("DirectXTex"); + + if (memcmp(&containerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0) + { + // Set Software name + (void)metawriter->SetMetadataByName(L"/tEXt/{str=Software}", &value); + + // Set sRGB chunk + if (sRGB) + { + value.vt = VT_UI1; + value.bVal = 0; + (void)metawriter->SetMetadataByName(L"/sRGB/RenderingIntent", &value); + } + else + { + // add gAMA chunk with gamma 1.0 + value.vt = VT_UI4; + value.uintVal = 100000; // gama value * 100,000 -- i.e. gamma 1.0 + (void)metawriter->SetMetadataByName(L"/gAMA/ImageGamma", &value); + + // remove sRGB chunk which is added by default. + (void)metawriter->RemoveMetadataByName(L"/sRGB/RenderingIntent"); + } + } +#if defined(_XBOX_ONE) && defined(_TITLE) + else if (memcmp(&containerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID)) == 0) + { + // Set Software name + (void)metawriter->SetMetadataByName(L"/app1/ifd/{ushort=305}", &value); + + if (sRGB) + { + // Set EXIF Colorspace of sRGB + value.vt = VT_UI2; + value.uiVal = 1; + (void)metawriter->SetMetadataByName(L"/app1/ifd/exif/{ushort=40961}", &value); + } + } + else if (memcmp(&containerFormat, &GUID_ContainerFormatTiff, sizeof(GUID)) == 0) + { + // Set Software name + (void)metawriter->SetMetadataByName(L"/ifd/{ushort=305}", &value); + + if (sRGB) + { + // Set EXIF Colorspace of sRGB + value.vt = VT_UI2; + value.uiVal = 1; + (void)metawriter->SetMetadataByName(L"/ifd/exif/{ushort=40961}", &value); + } + } +#else + else + { + // Set Software name + (void)metawriter->SetMetadataByName(L"System.ApplicationName", &value); + + if (sRGB) + { + // Set EXIF Colorspace of sRGB + value.vt = VT_UI2; + value.uiVal = 1; + (void)metawriter->SetMetadataByName(L"System.Image.ColorSpace", &value); + } + } +#endif + } + else if (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) + { + // Some formats just don't support metadata (BMP, ICO, etc.), so ignore this failure + hr = S_OK; + } + + return hr; + } + + + //------------------------------------------------------------------------------------- + // Encodes a single frame + //------------------------------------------------------------------------------------- + HRESULT EncodeImage( + const Image& image, + DWORD flags, + _In_ REFGUID containerFormat, + _In_ IWICBitmapFrameEncode* frame, + _In_opt_ IPropertyBag2* props, + _In_opt_ const GUID* targetFormat) + { + if (!frame) + return E_INVALIDARG; + + if (!image.pixels) + return E_POINTER; + + WICPixelFormatGUID pfGuid; + if (!_DXGIToWIC(image.format, pfGuid)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + HRESULT hr = frame->Initialize(props); + if (FAILED(hr)) + return hr; + + if ((image.width > UINT32_MAX) || (image.height > UINT32_MAX)) + return E_INVALIDARG; + + hr = frame->SetSize(static_cast(image.width), static_cast(image.height)); + if (FAILED(hr)) + return hr; + + hr = frame->SetResolution(72, 72); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID targetGuid = (targetFormat) ? (*targetFormat) : pfGuid; + hr = frame->SetPixelFormat(&targetGuid); + if (FAILED(hr)) + return hr; + + if (targetFormat && memcmp(targetFormat, &targetGuid, sizeof(WICPixelFormatGUID)) != 0) + { + // Requested output pixel format is not supported by the WIC codec + return E_FAIL; + } + + hr = EncodeMetadata(frame, containerFormat, image.format); + if (FAILED(hr)) + return hr; + + if (memcmp(&targetGuid, &pfGuid, sizeof(WICPixelFormatGUID)) != 0) + { + // Conversion required to write + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr source; + hr = pWIC->CreateBitmapFromMemory(static_cast(image.width), static_cast(image.height), pfGuid, + static_cast(image.rowPitch), static_cast(image.slicePitch), + image.pixels, source.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfGuid, targetGuid, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(source.Get(), targetGuid, _GetWICDither(flags), nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + WICRect rect = { 0, 0, static_cast(image.width), static_cast(image.height) }; + hr = frame->WriteSource(FC.Get(), &rect); + if (FAILED(hr)) + return hr; + } + else + { + // No conversion required + hr = frame->WritePixels(static_cast(image.height), static_cast(image.rowPitch), static_cast(image.slicePitch), + reinterpret_cast(image.pixels)); + if (FAILED(hr)) + return hr; + } + + hr = frame->Commit(); + if (FAILED(hr)) + return hr; + + return S_OK; + } + + HRESULT EncodeSingleFrame( + const Image& image, + DWORD flags, + _In_ REFGUID containerFormat, + _Inout_ IStream* stream, + _In_opt_ const GUID* targetFormat, + _In_opt_ std::function setCustomProps) + { + if (!stream) + return E_INVALIDARG; + + // Initialize WIC + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr encoder; + HRESULT hr = pWIC->CreateEncoder(containerFormat, 0, encoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = encoder->Initialize(stream, WICBitmapEncoderNoCache); + if (FAILED(hr)) + return hr; + + ComPtr frame; + ComPtr props; + hr = encoder->CreateNewFrame(frame.GetAddressOf(), props.GetAddressOf()); + if (FAILED(hr)) + return hr; + + if (memcmp(&containerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID)) == 0 && iswic2) + { + // Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel + PROPBAG2 option = { 0 }; + option.pstrName = const_cast(L"EnableV5Header32bppBGRA"); + + VARIANT varValue; + varValue.vt = VT_BOOL; + varValue.boolVal = VARIANT_TRUE; + (void)props->Write(1, &option, &varValue); + } + + if (setCustomProps) + { + setCustomProps(props.Get()); + } + + hr = EncodeImage(image, flags, containerFormat, frame.Get(), props.Get(), targetFormat); + if (FAILED(hr)) + return hr; + + hr = encoder->Commit(); + if (FAILED(hr)) + return hr; + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Encodes an image array + //------------------------------------------------------------------------------------- + HRESULT EncodeMultiframe( + _In_reads_(nimages) const Image* images, + size_t nimages, + DWORD flags, + _In_ REFGUID containerFormat, + _Inout_ IStream* stream, + _In_opt_ const GUID* targetFormat, + _In_opt_ std::function setCustomProps) + { + if (!stream || nimages < 2) + return E_INVALIDARG; + + if (!images) + return E_POINTER; + + // Initialize WIC + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr encoder; + HRESULT hr = pWIC->CreateEncoder(containerFormat, 0, encoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr einfo; + hr = encoder->GetEncoderInfo(einfo.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL mframe = FALSE; + hr = einfo->DoesSupportMultiframe(&mframe); + if (FAILED(hr)) + return hr; + + if (!mframe) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + hr = encoder->Initialize(stream, WICBitmapEncoderNoCache); + if (FAILED(hr)) + return hr; + + for (size_t index = 0; index < nimages; ++index) + { + ComPtr frame; + ComPtr props; + hr = encoder->CreateNewFrame(frame.GetAddressOf(), props.GetAddressOf()); + if (FAILED(hr)) + return hr; + + if (setCustomProps) + { + setCustomProps(props.Get()); + } + + hr = EncodeImage(images[index], flags, containerFormat, frame.Get(), props.Get(), targetFormat); + if (FAILED(hr)) + return hr; + } + + hr = encoder->Commit(); + if (FAILED(hr)) + return hr; + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Obtain metadata from WIC-supported file in memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromWICMemory( + const void* pSource, + size_t size, + DWORD flags, + TexMetadata& metadata, + std::function getMQR) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + if (size > UINT32_MAX) + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + // Create input stream for memory + ComPtr stream; + HRESULT hr = pWIC->CreateStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = stream->InitializeFromMemory(reinterpret_cast(const_cast(pSource)), + static_cast(size)); + if (FAILED(hr)) + return hr; + + // Initialize WIC + ComPtr decoder; + hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr frame; + hr = decoder->GetFrame(0, frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + // Get metadata + hr = DecodeMetadata(flags, iswic2, decoder.Get(), frame.Get(), metadata, nullptr, getMQR); + if (FAILED(hr)) + return hr; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Obtain metadata from WIC-supported file on disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromWICFile( + const wchar_t* szFile, + DWORD flags, + TexMetadata& metadata, + std::function getMQR) +{ + if (!szFile) + return E_INVALIDARG; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + // Initialize WIC + ComPtr decoder; + HRESULT hr = pWIC->CreateDecoderFromFilename(szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr frame; + hr = decoder->GetFrame(0, frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + // Get metadata + hr = DecodeMetadata(flags, iswic2, decoder.Get(), frame.Get(), metadata, nullptr, getMQR); + if (FAILED(hr)) + return hr; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Load a WIC-supported file in memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromWICMemory( + const void* pSource, + size_t size, + DWORD flags, + TexMetadata* metadata, + ScratchImage& image, + std::function getMQR) +{ + if (!pSource || size == 0) + return E_INVALIDARG; + + if (size > UINT32_MAX) + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + image.Release(); + + // Create input stream for memory + ComPtr stream; + HRESULT hr = pWIC->CreateStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = stream->InitializeFromMemory(reinterpret_cast(const_cast(pSource)), static_cast(size)); + if (FAILED(hr)) + return hr; + + // Initialize WIC + ComPtr decoder; + hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr frame; + hr = decoder->GetFrame(0, frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + // Get metadata + TexMetadata mdata; + WICPixelFormatGUID convertGUID = { 0 }; + hr = DecodeMetadata(flags, iswic2, decoder.Get(), frame.Get(), mdata, &convertGUID, getMQR); + if (FAILED(hr)) + return hr; + + if ((mdata.arraySize > 1) && (flags & WIC_FLAGS_ALL_FRAMES)) + { + hr = DecodeMultiframe(flags, mdata, decoder.Get(), image); + } + else + { + hr = DecodeSingleFrame(flags, mdata, convertGUID, frame.Get(), image); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Load a WIC-supported file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromWICFile( + const wchar_t* szFile, + DWORD flags, + TexMetadata* metadata, + ScratchImage& image, + std::function getMQR) +{ + if (!szFile) + return E_INVALIDARG; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + image.Release(); + + // Initialize WIC + ComPtr decoder; + HRESULT hr = pWIC->CreateDecoderFromFilename(szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr frame; + hr = decoder->GetFrame(0, frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + // Get metadata + TexMetadata mdata; + WICPixelFormatGUID convertGUID = { 0 }; + hr = DecodeMetadata(flags, iswic2, decoder.Get(), frame.Get(), mdata, &convertGUID, getMQR); + if (FAILED(hr)) + return hr; + + if ((mdata.arraySize > 1) && (flags & WIC_FLAGS_ALL_FRAMES)) + { + hr = DecodeMultiframe(flags, mdata, decoder.Get(), image); + } + else + { + hr = DecodeSingleFrame(flags, mdata, convertGUID, frame.Get(), image); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a WIC-supported file to memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToWICMemory( + const Image& image, + DWORD flags, + REFGUID containerFormat, + Blob& blob, + const GUID* targetFormat, + std::function setCustomProps) +{ + if (!image.pixels) + return E_POINTER; + + blob.Release(); + + ComPtr stream; + HRESULT hr = CreateMemoryStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = EncodeSingleFrame(image, flags, containerFormat, stream.Get(), targetFormat, setCustomProps); + if (FAILED(hr)) + return hr; + + // Copy stream data into blob + STATSTG stat; + hr = stream->Stat(&stat, STATFLAG_NONAME); + if (FAILED(hr)) + return hr; + + if (stat.cbSize.HighPart > 0) + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + + hr = blob.Initialize(stat.cbSize.LowPart); + if (FAILED(hr)) + return hr; + + LARGE_INTEGER li = { { 0 } }; + hr = stream->Seek(li, STREAM_SEEK_SET, 0); + if (FAILED(hr)) + return hr; + + DWORD bytesRead; + hr = stream->Read(blob.GetBufferPointer(), static_cast(blob.GetBufferSize()), &bytesRead); + if (FAILED(hr)) + return hr; + + if (bytesRead != blob.GetBufferSize()) + return E_FAIL; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::SaveToWICMemory( + const Image* images, + size_t nimages, + DWORD flags, + REFGUID containerFormat, + Blob& blob, + const GUID* targetFormat, + std::function setCustomProps) +{ + if (!images || nimages == 0) + return E_INVALIDARG; + + blob.Release(); + + ComPtr stream; + HRESULT hr = CreateMemoryStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + if (nimages > 1) + hr = EncodeMultiframe(images, nimages, flags, containerFormat, stream.Get(), targetFormat, setCustomProps); + else + hr = EncodeSingleFrame(images[0], flags, containerFormat, stream.Get(), targetFormat, setCustomProps); + + if (FAILED(hr)) + return hr; + + // Copy stream data into blob + STATSTG stat; + hr = stream->Stat(&stat, STATFLAG_NONAME); + if (FAILED(hr)) + return hr; + + if (stat.cbSize.HighPart > 0) + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + + hr = blob.Initialize(stat.cbSize.LowPart); + if (FAILED(hr)) + return hr; + + LARGE_INTEGER li = { { 0 } }; + hr = stream->Seek(li, STREAM_SEEK_SET, 0); + if (FAILED(hr)) + return hr; + + DWORD bytesRead; + hr = stream->Read(blob.GetBufferPointer(), static_cast(blob.GetBufferSize()), &bytesRead); + if (FAILED(hr)) + return hr; + + if (bytesRead != blob.GetBufferSize()) + return E_FAIL; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a WIC-supported file to disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToWICFile( + const Image& image, + DWORD flags, + REFGUID containerFormat, + const wchar_t* szFile, + const GUID* targetFormat, + std::function setCustomProps) +{ + if (!szFile) + return E_INVALIDARG; + + if (!image.pixels) + return E_POINTER; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr stream; + HRESULT hr = pWIC->CreateStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = stream->InitializeFromFilename(szFile, GENERIC_WRITE); + if (FAILED(hr)) + return hr; + + hr = EncodeSingleFrame(image, flags, containerFormat, stream.Get(), targetFormat, setCustomProps); + if (FAILED(hr)) + { + stream.Reset(); + DeleteFileW(szFile); + return hr; + } + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT DirectX::SaveToWICFile( + const Image* images, + size_t nimages, + DWORD flags, + REFGUID containerFormat, + const wchar_t* szFile, + const GUID* targetFormat, + std::function setCustomProps) +{ + if (!szFile || !images || nimages == 0) + return E_INVALIDARG; + + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr stream; + HRESULT hr = pWIC->CreateStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = stream->InitializeFromFilename(szFile, GENERIC_WRITE); + if (FAILED(hr)) + return hr; + + if (nimages > 1) + hr = EncodeMultiframe(images, nimages, flags, containerFormat, stream.Get(), targetFormat, setCustomProps); + else + hr = EncodeSingleFrame(images[0], flags, containerFormat, stream.Get(), targetFormat, setCustomProps); + + if (FAILED(hr)) + { + stream.Reset(); + DeleteFileW(szFile); + return hr; + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexXbox.h b/Kits/DirectXTex/DirectXTexXbox.h new file mode 100644 index 0000000000000000000000000000000000000000..45da8e91be2dbdda66e2189fe6a6e8b7b14c0584 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXbox.h @@ -0,0 +1,115 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexXbox.h +// +// DirectXTex Auxillary functions for Xbox One texture processing +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#ifndef _M_X64 +#error This tool is only supported for x64 native +#endif + +#include "directxtex.h" + +#include + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#define DIRECTX_TEX_XBOX_VERSION 101 + +namespace Xbox +{ + class XboxImage + { + public: + XboxImage() : dataSize(0), baseAlignment(0), tilemode(XG_TILE_MODE_INVALID), metadata{}, memory(nullptr) + { + } + ~XboxImage() + { + Release(); + } + + HRESULT Initialize( _In_ const XG_TEXTURE1D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0 ); + HRESULT Initialize( _In_ const XG_TEXTURE2D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0 ); + HRESULT Initialize( _In_ const XG_TEXTURE3D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0 ); + HRESULT Initialize( _In_ const DirectX::TexMetadata& mdata, _In_ XG_TILE_MODE tm, _In_ uint32_t size, _In_ uint32_t alignment ); + + void Release(); + + const DirectX::TexMetadata& GetMetadata() const { return metadata; } + XG_TILE_MODE GetTileMode() const { return tilemode; } + + uint32_t GetSize() const { return dataSize; } + uint32_t GetAlignment() const { return baseAlignment; } + uint8_t* GetPointer() const { return memory; } + + private: + uint32_t dataSize; + uint32_t baseAlignment; + XG_TILE_MODE tilemode; + DirectX::TexMetadata metadata; + uint8_t* memory; + + // Hide copy constructor and assignment operator + XboxImage( const XboxImage& ); + XboxImage& operator=( const XboxImage& ); + }; + + //--------------------------------------------------------------------------------- + // Image I/O + + HRESULT GetMetadataFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, + _Out_ DirectX::TexMetadata& metadata, _Out_ bool& isXbox ); + HRESULT GetMetadataFromDDSFile( _In_z_ const wchar_t* szFile, _Out_ DirectX::TexMetadata& metadata, _Out_ bool& isXbox ); + + HRESULT LoadFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, + _Out_opt_ DirectX::TexMetadata* metadata, _Out_ XboxImage& image ); + HRESULT LoadFromDDSFile( _In_z_ const wchar_t* szFile, + _Out_opt_ DirectX::TexMetadata* metadata, _Out_ XboxImage& image ); + + HRESULT SaveToDDSMemory( _In_ const XboxImage& xbox, _Out_ DirectX::Blob& blob ); + HRESULT SaveToDDSFile( _In_ const XboxImage& xbox, _In_z_ const wchar_t* szFile ); + + //--------------------------------------------------------------------------------- + // Xbox One Texture Tiling / Detiling (requires XG DLL to be present at runtime) + + HRESULT Tile( _In_ const DirectX::Image& srcImage, _Out_ XboxImage& xbox, _In_ XG_TILE_MODE mode = XG_TILE_MODE_INVALID ); + HRESULT Tile( _In_ const DirectX::Image* srcImages, _In_ size_t nimages, _In_ const DirectX::TexMetadata& metadata, + _Out_ XboxImage& xbox, _In_ XG_TILE_MODE mode = XG_TILE_MODE_INVALID ); + + HRESULT Detile( _In_ const XboxImage& xbox, _Out_ DirectX::ScratchImage& image ); + + //--------------------------------------------------------------------------------- + // Direct3D 11.X functions + +#if defined(_XBOX_ONE) && defined(_TITLE) && defined(__d3d11_x_h__) + + HRESULT CreateTexture( _In_ ID3D11DeviceX* d3dDevice, + _In_ const XboxImage& xbox, _Outptr_opt_ ID3D11Resource** ppResource, _Outptr_ void** grfxMemory ); + + HRESULT CreateShaderResourceView( _In_ ID3D11DeviceX* d3dDevice, + _In_ const XboxImage& xbox, _Outptr_opt_ ID3D11ShaderResourceView** ppSRV, _Outptr_ void** grfxMemory ); + + void FreeTextureMemory( _In_ ID3D11DeviceX* d3dDevice, _In_opt_ void* grfxMemory ); + +#endif + + //--------------------------------------------------------------------------------- + // Direct3D 12.X functions + +#if defined(_XBOX_ONE) && defined(_TITLE) && defined(__d3d12_x_h__) + + HRESULT CreateTexture( _In_ ID3D12Device* d3dDevice, + _In_ const XboxImage& xbox, _Outptr_opt_ ID3D12Resource** ppResource, _Outptr_ void** grfxMemory ); + + void FreeTextureMemory( _In_ ID3D12Device* d3dDevice, _In_opt_ void* grfxMemory ); + +#endif + +}; // namespace diff --git a/Kits/DirectXTex/DirectXTexXboxD3D11X.cpp b/Kits/DirectXTex/DirectXTexXboxD3D11X.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3cea048ad39813527bbbf68ded787f9d9af37af4 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXboxD3D11X.cpp @@ -0,0 +1,248 @@ +//------------------------------------------------------------------------------------- +// DirectXTexD3D11X.cpp +// +// DirectXTex Auxillary functions for creating resouces from XboxImage containers +// via the CreatePlacement APIs +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" +#include "DirectXTexXbox.h" + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#error This module only supports Xbox One exclusive apps +#endif + +using namespace Xbox; +using Microsoft::WRL::ComPtr; + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Create a texture resource +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateTexture( + ID3D11DeviceX* d3dDevice, + const XboxImage& xbox, + ID3D11Resource** ppResource, + void** grfxMemory) +{ + if (!d3dDevice || !ppResource || !grfxMemory) + return E_INVALIDARG; + + *grfxMemory = nullptr; + *ppResource = nullptr; + + if (!xbox.GetPointer() || !xbox.GetAlignment() || !xbox.GetSize() || xbox.GetTileMode() == XG_TILE_MODE_INVALID) + return E_INVALIDARG; + + // Allocate graphics memory + size_t sizeBytes = (size_t(xbox.GetSize()) + 0xFFF) & ~0xFFF; // 4K boundary + size_t alignmentBytes = std::max(xbox.GetAlignment(), 4096); + + HRESULT hr = D3DAllocateGraphicsMemory(sizeBytes, alignmentBytes, 0, D3D11_GRAPHICS_MEMORY_ACCESS_CPU_CACHE_COHERENT, grfxMemory); + if (FAILED(hr)) + { + *grfxMemory = nullptr; + return hr; + } + + assert(*grfxMemory != 0); + + // Copy tiled data into graphics memory + memcpy(*grfxMemory, xbox.GetPointer(), xbox.GetSize()); + + // Create texture resource + auto& metadata = xbox.GetMetadata(); + + switch (metadata.dimension) + { + case DirectX::TEX_DIMENSION_TEXTURE1D: + { + D3D11_TEXTURE1D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = metadata.format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ID3D11Texture1D* tex = nullptr; + hr = d3dDevice->CreatePlacementTexture1D(&desc, xbox.GetTileMode(), 0, *grfxMemory, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + *ppResource = tex; + } + } + break; + + case DirectX::TEX_DIMENSION_TEXTURE2D: + { + D3D11_TEXTURE2D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = metadata.format; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.MiscFlags = (metadata.miscFlags & DirectX::TEX_MISC_TEXTURECUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; + + ID3D11Texture2D* tex = nullptr; + hr = d3dDevice->CreatePlacementTexture2D(&desc, xbox.GetTileMode(), 0, *grfxMemory, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + *ppResource = tex; + } + } + break; + + case DirectX::TEX_DIMENSION_TEXTURE3D: + { + D3D11_TEXTURE3D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.Depth = static_cast(metadata.depth); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.Format = metadata.format; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ID3D11Texture3D* tex = nullptr; + hr = d3dDevice->CreatePlacementTexture3D(&desc, xbox.GetTileMode(), 0, *grfxMemory, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + *ppResource = tex; + } + } + break; + + default: + hr = E_FAIL; + break; + } + + if (FAILED(hr)) + { + (void)D3DFreeGraphicsMemory(*grfxMemory); + *grfxMemory = nullptr; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Create a shader resource view and associated texture +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateShaderResourceView( + ID3D11DeviceX* d3dDevice, + const XboxImage& xbox, + ID3D11ShaderResourceView** ppSRV, + void** grfxMemory) +{ + if (!ppSRV) + return E_INVALIDARG; + + *ppSRV = nullptr; + + ComPtr resource; + HRESULT hr = CreateTexture(d3dDevice, xbox, resource.GetAddressOf(), grfxMemory); + if (FAILED(hr)) + return hr; + + assert(resource); + + auto& metadata = xbox.GetMetadata(); + + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; + SRVDesc.Format = metadata.format; + + switch (metadata.dimension) + { + case DirectX::TEX_DIMENSION_TEXTURE1D: + if (metadata.arraySize > 1) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + SRVDesc.Texture1DArray.MipLevels = static_cast(metadata.mipLevels); + SRVDesc.Texture1DArray.ArraySize = static_cast(metadata.arraySize); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MipLevels = static_cast(metadata.mipLevels); + } + break; + + case DirectX::TEX_DIMENSION_TEXTURE2D: + if (metadata.IsCubemap()) + { + if (metadata.arraySize > 6) + { + assert((metadata.arraySize % 6) == 0); + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; + SRVDesc.TextureCubeArray.MipLevels = static_cast(metadata.mipLevels); + SRVDesc.TextureCubeArray.NumCubes = static_cast(metadata.arraySize / 6); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MipLevels = static_cast(metadata.mipLevels); + } + } + else if (metadata.arraySize > 1) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + SRVDesc.Texture2DArray.MipLevels = static_cast(metadata.mipLevels); + SRVDesc.Texture2DArray.ArraySize = static_cast(metadata.arraySize); + } + else + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = static_cast(metadata.mipLevels); + } + break; + + case DirectX::TEX_DIMENSION_TEXTURE3D: + assert(metadata.arraySize == 1); + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MipLevels = static_cast(metadata.mipLevels); + break; + + default: + assert(grfxMemory != 0); + (void)D3DFreeGraphicsMemory(*grfxMemory); + *grfxMemory = nullptr; + return E_FAIL; + } + + hr = d3dDevice->CreateShaderResourceView(resource.Get(), &SRVDesc, ppSRV); + if (FAILED(hr)) + { + (void)D3DFreeGraphicsMemory(*grfxMemory); + *grfxMemory = nullptr; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Free allocated graphics memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void Xbox::FreeTextureMemory(ID3D11DeviceX* d3dDevice, void* grfxMemory) +{ + UNREFERENCED_PARAMETER(d3dDevice); // used only for overload resolution + + if (grfxMemory) + { + (void)D3DFreeGraphicsMemory(grfxMemory); + } +} \ No newline at end of file diff --git a/Kits/DirectXTex/DirectXTexXboxD3D12X.cpp b/Kits/DirectXTex/DirectXTexXboxD3D12X.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4116f7207a3c559c6298f18b9ad150feb3d4bbfe --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXboxD3D12X.cpp @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------------- +// DirectXTexD3D12X.cpp +// +// DirectXTex Auxillary functions for creating resouces from XboxImage containers +// via the CreatePlacedResourceX API +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#include "directxtexp.h" +#include "DirectXTexXbox.h" + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#error This module only supports Xbox One exclusive apps +#endif + +using namespace Xbox; +using Microsoft::WRL::ComPtr; + +namespace +{ + //-------------------------------------------------------------------------------------- + // Default XMemAlloc attributes for texture loading + //-------------------------------------------------------------------------------------- + const uint64_t c_XMemAllocAttributes = MAKE_XALLOC_ATTRIBUTES( + eXALLOCAllocatorId_MiddlewareReservedMin, + 0, + XALLOC_MEMTYPE_GRAPHICS_WRITECOMBINE_GPU_READONLY, + XALLOC_PAGESIZE_64KB, + XALLOC_ALIGNMENT_64K); +}; + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Create a texture resource +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::CreateTexture( + ID3D12Device* d3dDevice, + const XboxImage& xbox, + ID3D12Resource** ppResource, + void** grfxMemory) +{ + if (!d3dDevice || !ppResource || !grfxMemory) + return E_INVALIDARG; + + *grfxMemory = nullptr; + *ppResource = nullptr; + + if (!xbox.GetPointer() || !xbox.GetAlignment() || !xbox.GetSize() || xbox.GetTileMode() == XG_TILE_MODE_INVALID) + return E_INVALIDARG; + + // Allocate graphics memory + *grfxMemory = XMemAlloc(xbox.GetSize(), c_XMemAllocAttributes); + if (!*grfxMemory) + return E_OUTOFMEMORY; + + // Copy tiled data into graphics memory + memcpy(*grfxMemory, xbox.GetPointer(), xbox.GetSize()); + + // Create texture resource + auto& metadata = xbox.GetMetadata(); + + D3D12_RESOURCE_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.DepthOrArraySize = (metadata.dimension == DirectX::TEX_DIMENSION_TEXTURE3D) ? static_cast(metadata.depth) : static_cast(metadata.arraySize); + desc.Format = metadata.format; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Dimension = static_cast(metadata.dimension); + desc.Layout = static_cast(0x100 | xbox.GetTileMode()); + + HRESULT hr = d3dDevice->CreatePlacedResourceX( + reinterpret_cast(*grfxMemory), + &desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + nullptr, + IID_GRAPHICS_PPV_ARGS(ppResource)); + + if (FAILED(hr)) + { + XMemFree(*grfxMemory, c_XMemAllocAttributes); + *grfxMemory = nullptr; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Free allocated graphics memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +void Xbox::FreeTextureMemory(ID3D12Device* d3dDevice, void* grfxMemory) +{ + UNREFERENCED_PARAMETER(d3dDevice); // used only for overload resolution + + if (grfxMemory) + { + XMemFree(grfxMemory, c_XMemAllocAttributes); + } +} \ No newline at end of file diff --git a/Kits/DirectXTex/DirectXTexXboxDDS.cpp b/Kits/DirectXTex/DirectXTexXboxDDS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..783a5c2be4d2bc3b9f2f0b49b435e5bff7901245 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXboxDDS.cpp @@ -0,0 +1,707 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexXboxDDS.cpp +// +// DirectXTex Auxillary functions for saving "XBOX" Xbox One variants of DDS files +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "DirectXTexP.h" +#include "DirectXTexXbox.h" + +#include "dds.h" +#include "xdk.h" + +using namespace DirectX; +using namespace Xbox; + +namespace +{ + const DDS_PIXELFORMAT DDSPF_XBOX = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('X','B','O','X'), 0, 0, 0, 0, 0 }; + +#pragma pack(push,1) + + struct DDS_HEADER_XBOX + // Must match structure in XboxDDSTextureLoader module + { + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 + uint32_t tileMode; // see XG_TILE_MODE + uint32_t baseAlignment; + uint32_t dataSize; + uint32_t xdkVer; // matching _XDK_VER + }; + +#pragma pack(pop) + + static_assert(sizeof(DDS_HEADER_XBOX) == 36, "DDS XBOX Header size mismatch"); + static_assert(sizeof(DDS_HEADER_XBOX) >= sizeof(DDS_HEADER_DXT10), "DDS XBOX Header should be larger than DX10 header"); + + static const size_t XBOX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_XBOX); + + //------------------------------------------------------------------------------------- + // Decodes DDS header using XBOX extended header (variant of DX10 header) + //------------------------------------------------------------------------------------- + HRESULT DecodeDDSHeader( + _In_reads_bytes_(size) const void* pSource, + size_t size, + DirectX::TexMetadata& metadata, + _Out_opt_ XG_TILE_MODE* tmode, + _Out_opt_ uint32_t* dataSize, + _Out_opt_ uint32_t* baseAlignment) + { + if (!pSource) + return E_INVALIDARG; + + if (tmode) + *tmode = XG_TILE_MODE_INVALID; + if (dataSize) + *dataSize = 0; + if (baseAlignment) + *baseAlignment = 0; + + memset(&metadata, 0, sizeof(TexMetadata)); + + if (size < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + // DDS files always start with the same magic number ("DDS ") + uint32_t dwMagicNumber = *reinterpret_cast(pSource); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto pHeader = reinterpret_cast(reinterpret_cast(pSource) + sizeof(uint32_t)); + + // Verify header to validate DDS file + if (pHeader->dwSize != sizeof(DDS_HEADER) + || pHeader->ddspf.dwSize != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + metadata.mipLevels = pHeader->dwMipMapCount; + if (metadata.mipLevels == 0) + metadata.mipLevels = 1; + + // Check for XBOX extension + if (!(pHeader->ddspf.dwFlags & DDS_FOURCC) + || (MAKEFOURCC('X', 'B', 'O', 'X') != pHeader->ddspf.dwFourCC)) + { + // We know it's a DDS file, but it's not an XBOX extension + return S_FALSE; + } + + // Buffer must be big enough for both headers and magic value + if (size < XBOX_HEADER_SIZE) + { + return E_FAIL; + } + + auto xboxext = reinterpret_cast( + reinterpret_cast(pSource) + sizeof(uint32_t) + sizeof(DDS_HEADER)); + + if (xboxext->xdkVer < _XDK_VER) + { + OutputDebugStringA("WARNING: DDS XBOX file may be outdated and need regeneration\n"); + } + + metadata.arraySize = xboxext->arraySize; + if (metadata.arraySize == 0) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + metadata.format = xboxext->dxgiFormat; + if (!IsValid(metadata.format)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + static_assert(TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch"); + + metadata.miscFlags = xboxext->miscFlag & ~TEX_MISC_TEXTURECUBE; + + switch (xboxext->resourceDimension) + { + case DDS_DIMENSION_TEXTURE1D: + + if ((pHeader->dwFlags & DDS_HEIGHT) && pHeader->dwHeight != 1) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + metadata.width = pHeader->dwWidth; + metadata.height = 1; + metadata.depth = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE1D; + break; + + case DDS_DIMENSION_TEXTURE2D: + if (xboxext->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) + { + metadata.miscFlags |= TEX_MISC_TEXTURECUBE; + metadata.arraySize *= 6; + } + + metadata.width = pHeader->dwWidth; + metadata.height = pHeader->dwHeight; + metadata.depth = 1; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + break; + + case DDS_DIMENSION_TEXTURE3D: + if (!(pHeader->dwFlags & DDS_HEADER_FLAGS_VOLUME)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + if (metadata.arraySize > 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + metadata.width = pHeader->dwWidth; + metadata.height = pHeader->dwHeight; + metadata.depth = pHeader->dwDepth; + metadata.dimension = TEX_DIMENSION_TEXTURE3D; + break; + + default: + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + static_assert(TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch"); + + static_assert(TEX_ALPHA_MODE_UNKNOWN == DDS_ALPHA_MODE_UNKNOWN, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_CUSTOM == DDS_ALPHA_MODE_CUSTOM, "DDS header mismatch"); + + metadata.miscFlags2 = xboxext->miscFlags2; + + if (tmode) + *tmode = static_cast(xboxext->tileMode); + + if (baseAlignment) + *baseAlignment = xboxext->baseAlignment; + + if (dataSize) + *dataSize = xboxext->dataSize; + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // Encodes DDS file header (magic value, header, XBOX extended header) + //------------------------------------------------------------------------------------- + HRESULT EncodeDDSHeader( + const XboxImage& xbox, + _Out_writes_(maxsize) void* pDestination, + size_t maxsize) + { + if (!pDestination) + return E_POINTER; + + if (maxsize < XBOX_HEADER_SIZE) + return E_NOT_SUFFICIENT_BUFFER; + + *reinterpret_cast(pDestination) = DDS_MAGIC; + + auto header = reinterpret_cast(reinterpret_cast(pDestination) + sizeof(uint32_t)); + + memset(header, 0, sizeof(DDS_HEADER)); + header->dwSize = sizeof(DDS_HEADER); + header->dwFlags = DDS_HEADER_FLAGS_TEXTURE; + header->dwCaps = DDS_SURFACE_FLAGS_TEXTURE; + + auto& metadata = xbox.GetMetadata(); + + if (metadata.mipLevels > 0) + { + header->dwFlags |= DDS_HEADER_FLAGS_MIPMAP; + + if (metadata.mipLevels > UINT32_MAX) + return E_INVALIDARG; + + header->dwMipMapCount = static_cast(metadata.mipLevels); + + if (header->dwMipMapCount > 1) + header->dwCaps |= DDS_SURFACE_FLAGS_MIPMAP; + } + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (metadata.width > UINT32_MAX) + return E_INVALIDARG; + + header->dwWidth = static_cast(metadata.width); + header->dwHeight = header->dwDepth = 1; + break; + + case TEX_DIMENSION_TEXTURE2D: + if (metadata.height > UINT32_MAX + || metadata.width > UINT32_MAX) + return E_INVALIDARG; + + header->dwHeight = static_cast(metadata.height); + header->dwWidth = static_cast(metadata.width); + header->dwDepth = 1; + + if (metadata.IsCubemap()) + { + header->dwCaps |= DDS_SURFACE_FLAGS_CUBEMAP; + header->dwCaps2 |= DDS_CUBEMAP_ALLFACES; + } + break; + + case TEX_DIMENSION_TEXTURE3D: + if (metadata.height > UINT32_MAX + || metadata.width > UINT32_MAX + || metadata.depth > UINT32_MAX) + return E_INVALIDARG; + + header->dwFlags |= DDS_HEADER_FLAGS_VOLUME; + header->dwCaps2 |= DDS_FLAGS_VOLUME; + header->dwHeight = static_cast(metadata.height); + header->dwWidth = static_cast(metadata.width); + header->dwDepth = static_cast(metadata.depth); + break; + + default: + return E_FAIL; + } + + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE); + + if (slicePitch > UINT32_MAX + || rowPitch > UINT32_MAX) + return E_FAIL; + + if (IsCompressed(metadata.format)) + { + header->dwFlags |= DDS_HEADER_FLAGS_LINEARSIZE; + header->dwPitchOrLinearSize = static_cast(slicePitch); + } + else + { + header->dwFlags |= DDS_HEADER_FLAGS_PITCH; + header->dwPitchOrLinearSize = static_cast(rowPitch); + } + + memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_XBOX, sizeof(DDS_PIXELFORMAT)); + + // Setup XBOX extended header + auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + + memset(xboxext, 0, sizeof(DDS_HEADER_XBOX)); + xboxext->dxgiFormat = metadata.format; + xboxext->resourceDimension = metadata.dimension; + + if (metadata.arraySize > UINT32_MAX) + return E_INVALIDARG; + + static_assert(TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch"); + xboxext->miscFlag = metadata.miscFlags & ~TEX_MISC_TEXTURECUBE; + + if (metadata.miscFlags & TEX_MISC_TEXTURECUBE) + { + xboxext->miscFlag |= TEX_MISC_TEXTURECUBE; + assert((metadata.arraySize % 6) == 0); + xboxext->arraySize = static_cast(metadata.arraySize / 6); + } + else + { + xboxext->arraySize = static_cast(metadata.arraySize); + } + + static_assert(TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch"); + + static_assert(TEX_ALPHA_MODE_UNKNOWN == DDS_ALPHA_MODE_UNKNOWN, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch"); + static_assert(TEX_ALPHA_MODE_CUSTOM == DDS_ALPHA_MODE_CUSTOM, "DDS header mismatch"); + + xboxext->miscFlags2 = metadata.miscFlags2; + + xboxext->tileMode = xbox.GetTileMode(); + xboxext->baseAlignment = xbox.GetAlignment(); + xboxext->dataSize = xbox.GetSize(); + xboxext->xdkVer = _XDK_VER; + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Obtain metadata from DDS file in memory/on disk +//------------------------------------------------------------------------------------- + +_Use_decl_annotations_ +HRESULT Xbox::GetMetadataFromDDSMemory( + const void* pSource, + size_t size, + TexMetadata& metadata, + bool& isXbox) +{ + if (!pSource || !size) + return E_INVALIDARG; + + isXbox = false; + + HRESULT hr = DecodeDDSHeader(pSource, size, metadata, nullptr, nullptr, nullptr); + + if (hr == S_FALSE) + { + hr = DirectX::GetMetadataFromDDSMemory(pSource, size, DirectX::DDS_FLAGS_NONE, metadata); + } + else if (SUCCEEDED(hr)) + { + isXbox = true; + } + + return hr; +} + +_Use_decl_annotations_ +HRESULT Xbox::GetMetadataFromDDSFile( + const wchar_t* szFile, + TexMetadata& metadata, + bool& isXbox) +{ + if (!szFile) + return E_INVALIDARG; + + isXbox = false; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, 0))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid DDS file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the standard header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // Read the header in (including extended header if present) + uint8_t header[XBOX_HEADER_SIZE]; + + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, XBOX_HEADER_SIZE, &bytesRead, 0)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + HRESULT hr = DecodeDDSHeader(header, bytesRead, metadata, nullptr, nullptr, nullptr); + + if (hr == S_FALSE) + { + hr = DirectX::GetMetadataFromDDSMemory(header, bytesRead, DirectX::DDS_FLAGS_NONE, metadata); + } + else if (SUCCEEDED(hr)) + { + isXbox = true; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Load a DDS file in memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::LoadFromDDSMemory( + const void* pSource, + size_t size, + TexMetadata* metadata, + XboxImage& xbox) +{ + if (!pSource || !size) + return E_INVALIDARG; + + xbox.Release(); + + TexMetadata mdata; + uint32_t dataSize; + uint32_t baseAlignment; + XG_TILE_MODE tmode; + HRESULT hr = DecodeDDSHeader(pSource, size, mdata, &tmode, &dataSize, &baseAlignment); + if (hr == S_FALSE) + { + // It's a DDS, but not an XBOX variant + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + if (FAILED(hr)) + { + return hr; + } + + if (!dataSize || !baseAlignment) + { + return E_FAIL; + } + + if (size <= XBOX_HEADER_SIZE) + { + return E_FAIL; + } + + // Copy tiled data + size_t remaining = size - XBOX_HEADER_SIZE; + + if (remaining < dataSize) + { + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } + + hr = xbox.Initialize(mdata, tmode, dataSize, baseAlignment); + if (FAILED(hr)) + return hr; + + assert(xbox.GetPointer() != 0); + + memcpy(xbox.GetPointer(), reinterpret_cast(pSource) + XBOX_HEADER_SIZE, dataSize); + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Load a DDS file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::LoadFromDDSFile( + const wchar_t* szFile, + TexMetadata* metadata, + XboxImage& xbox) +{ + if (!szFile) + return E_INVALIDARG; + + xbox.Release(); + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, 0))); +#endif + + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid DDS file) + if (fileInfo.EndOfFile.HighPart > 0) + { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + // Need at least enough data to fill the standard header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // Read the header in (including extended header if present) + uint8_t header[XBOX_HEADER_SIZE]; + + DWORD bytesRead = 0; + if (!ReadFile(hFile.get(), header, XBOX_HEADER_SIZE, &bytesRead, 0)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + TexMetadata mdata; + XG_TILE_MODE tmode; + uint32_t dataSize; + uint32_t baseAlignment; + HRESULT hr = DecodeDDSHeader(header, bytesRead, mdata, &tmode, &dataSize, &baseAlignment); + if (hr == S_FALSE) + { + // It's a DDS, but not an XBOX variant + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + if (FAILED(hr)) + return hr; + + if (!dataSize || !baseAlignment) + { + return E_FAIL; + } + + // Read tiled data + DWORD remaining = fileInfo.EndOfFile.LowPart - XBOX_HEADER_SIZE; + if (remaining == 0) + return E_FAIL; + + if (remaining < dataSize) + { + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } + + hr = xbox.Initialize(mdata, tmode, dataSize, baseAlignment); + if (FAILED(hr)) + return hr; + + assert(xbox.GetPointer() != 0); + + if (!ReadFile(hFile.get(), xbox.GetPointer(), dataSize, &bytesRead, 0)) + { + xbox.Release(); + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (metadata) + memcpy(metadata, &mdata, sizeof(TexMetadata)); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a DDS file to memory +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::SaveToDDSMemory(const XboxImage& xbox, Blob& blob) +{ + if (!xbox.GetPointer() || !xbox.GetSize() || !xbox.GetAlignment()) + return E_INVALIDARG; + + blob.Release(); + + HRESULT hr = blob.Initialize(XBOX_HEADER_SIZE + xbox.GetSize()); + if (FAILED(hr)) + return hr; + + // Copy header + auto pDestination = reinterpret_cast(blob.GetBufferPointer()); + assert(pDestination); + + hr = EncodeDDSHeader(xbox, pDestination, XBOX_HEADER_SIZE); + if (FAILED(hr)) + { + blob.Release(); + return hr; + } + + // Copy tiled data + size_t remaining = blob.GetBufferSize() - XBOX_HEADER_SIZE; + pDestination += XBOX_HEADER_SIZE; + + if (!remaining) + { + blob.Release(); + return E_FAIL; + } + + if (remaining < xbox.GetSize()) + { + blob.Release(); + return E_UNEXPECTED; + } + + memcpy(pDestination, xbox.GetPointer(), xbox.GetSize()); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Save a DDS file to disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::SaveToDDSFile(const XboxImage& xbox, const wchar_t* szFile) +{ + if (!szFile || !xbox.GetPointer() || !xbox.GetSize() || !xbox.GetAlignment()) + return E_INVALIDARG; + + // Create DDS Header + uint8_t header[XBOX_HEADER_SIZE]; + HRESULT hr = EncodeDDSHeader(xbox, header, XBOX_HEADER_SIZE); + if (FAILED(hr)) + return hr; + + // Create file and write header +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, 0))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + DWORD bytesWritten; + if (!WriteFile(hFile.get(), header, static_cast(XBOX_HEADER_SIZE), &bytesWritten, 0)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != XBOX_HEADER_SIZE) + { + return E_FAIL; + } + + // Write tiled data + if (!WriteFile(hFile.get(), xbox.GetPointer(), static_cast(xbox.GetSize()), &bytesWritten, 0)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesWritten != xbox.GetSize()) + { + return E_FAIL; + } + + return S_OK; +} diff --git a/Kits/DirectXTex/DirectXTexXboxDetile.cpp b/Kits/DirectXTex/DirectXTexXboxDetile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f557fdec68042c2317136f29382d42ec87d5d9ad --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXboxDetile.cpp @@ -0,0 +1,767 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexXboxDetile.cpp +// +// DirectXTex Auxillary functions for converting from Xbox One tiled to linear +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "DirectXTexP.h" +#include "DirectXTexXbox.h" + +using Microsoft::WRL::ComPtr; +using namespace DirectX; +using namespace Xbox; + +namespace +{ + //---------------------------------------------------------------------------------- + inline HRESULT DetileByElement1D( + const XboxImage& xbox, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + _In_reads_(nimages) const Image** result, + size_t nimages, + size_t bpp, + size_t w) + { + auto& mip = layout.Plane[0].MipLayout[level]; + + const uint8_t* sptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = sptr + mip.SizeBytes; + + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = result[item]; + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == result[0]->width); + assert(img->height == result[0]->height); + assert(img->rowPitch == result[0]->rowPitch); + assert(img->format == result[0]->format); + + uint8_t* dptr = img->pixels; + + for (size_t x = 0; x < w; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, 0, item, 0); + + const uint8_t* src = sptr + offset - mip.OffsetBytes; + + if ((src + bpp) > endPtr) + return E_FAIL; + + memcpy(dptr, src, bpp); + dptr += bpp; + } + } + + return S_OK; + } + + //---------------------------------------------------------------------------------- + inline HRESULT DetileByElement2D( + const XboxImage& xbox, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + _In_reads_(nimages) const Image** result, + size_t nimages, + size_t bpp, + size_t w, + size_t h) + { + auto& mip = layout.Plane[0].MipLayout[level]; + + const uint8_t* sptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = sptr + mip.SizeBytes; + + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = result[item]; + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == result[0]->width); + assert(img->height == result[0]->height); + assert(img->rowPitch == result[0]->rowPitch); + assert(img->format == result[0]->format); + + uint8_t* dptr = img->pixels; + + for (uint32_t y = 0; y < h; ++y) + { + uint8_t* tptr = dptr; + + for (size_t x = 0; x < w; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, item, 0); + + const uint8_t* src = sptr + offset - mip.OffsetBytes; + + if ((src + bpp) > endPtr) + return E_FAIL; + + memcpy(tptr, src, bpp); + tptr += bpp; + } + + dptr += img->rowPitch; + } + } + + return S_OK; + } + + //---------------------------------------------------------------------------------- + inline HRESULT DetileByElement3D( + const XboxImage& xbox, + uint32_t level, + uint32_t slices, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const Image& result, + size_t bpp, + size_t w, + size_t h) + { + auto& mip = layout.Plane[0].MipLayout[level]; + + const uint8_t* sptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = sptr + mip.SizeBytes; + + uint8_t* dptr = result.pixels; + + for (uint32_t z = 0; z < slices; ++z) + { + uint8_t* rptr = dptr; + + for (uint32_t y = 0; y < h; ++y) + { + uint8_t* tptr = rptr; + + for (size_t x = 0; x < w; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, z, 0); + + const uint8_t* src = sptr + offset - mip.OffsetBytes; + + if ((src + bpp) > endPtr) + return E_FAIL; + + memcpy(tptr, src, bpp); + tptr += bpp; + } + + rptr += result.rowPitch; + } + + dptr += result.slicePitch; + } + + return S_OK; + } + + //------------------------------------------------------------------------------------- + // 1D Tiling + //------------------------------------------------------------------------------------- + HRESULT Detile1D( + const XboxImage& xbox, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + _In_reads_(nimages) const Image** result, + size_t nimages) + { + if (!nimages) + return E_INVALIDARG; + + if (!xbox.GetPointer() || !computer || !result || !result[0]) + return E_POINTER; + + assert(layout.Planes == 1); + + DXGI_FORMAT format = result[0]->format; + + assert(format == xbox.GetMetadata().format); + + assert(!IsCompressed(format)); + + if (IsTypeless(format)) + { + //--- Typeless is done with per-element copy ---------------------------------- + size_t bpp = (BitsPerPixel(format) + 7) / 8; + size_t w = result[0]->width; + + assert(bpp == layout.Plane[0].BytesPerElement); + assert(w == layout.Plane[0].MipLayout[level].WidthElements); + + return DetileByElement1D(xbox, level, computer, layout, result, nimages, bpp, w); + } + else + { + //--- Standard format handling ------------------------------------------------ + auto& mip = layout.Plane[0].MipLayout[level]; + + size_t tiledPixels = mip.PitchPixels * mip.PaddedDepthOrArraySize; + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * (tiledPixels + result[0]->width), 16))); + + XMVECTOR* target = scanline.get(); + XMVECTOR* tiled = target + result[0]->width; + +#ifdef _DEBUG + memset(target, 0xCD, sizeof(XMVECTOR) * result[0]->width); + memset(tiled, 0xDD, sizeof(XMVECTOR) * tiledPixels); +#endif + + // Load tiled texture + if ((xbox.GetSize() - mip.OffsetBytes) < mip.SizeBytes) + return E_FAIL; + + if (!_LoadScanline(tiled, tiledPixels, xbox.GetPointer() + mip.OffsetBytes, mip.SizeBytes, xbox.GetMetadata().format)) + return E_FAIL; + + // Perform detiling + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = result[item]; + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == result[0]->width); + assert(img->height == result[0]->height); + assert(img->rowPitch == result[0]->rowPitch); + assert(img->format == result[0]->format); + + for (size_t x = 0; x < img->width; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, 0, item, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + offset = (offset - mip.OffsetBytes) / layout.Plane[0].BytesPerElement; + assert(offset < tiledPixels); + + target[x] = tiled[offset]; + } + + if (!_StoreScanline(img->pixels, img->rowPitch, img->format, target, img->width)) + return E_FAIL; + } + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // 2D Tiling + //------------------------------------------------------------------------------------- + HRESULT Detile2D( + const XboxImage& xbox, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + _In_reads_(nimages) const Image** result, + size_t nimages) + { + if (!nimages) + return E_INVALIDARG; + + if (!xbox.GetPointer() || !computer || !result || !result[0]) + return E_POINTER; + + assert(xbox.GetMetadata().format == result[0]->format); + + assert(layout.Planes == 1); + + DXGI_FORMAT format = result[0]->format; + + assert(format == xbox.GetMetadata().format); + + if (IsCompressed(format)) + { + //--- BC formats use per-block copy ------------------------------------------- + size_t nbw = std::max(1, (result[0]->width + 3) / 4); + size_t nbh = std::max(1, (result[0]->height + 3) / 4); + + size_t bpb = (format == DXGI_FORMAT_BC1_TYPELESS + || format == DXGI_FORMAT_BC1_UNORM + || format == DXGI_FORMAT_BC1_UNORM_SRGB + || format == DXGI_FORMAT_BC4_TYPELESS + || format == DXGI_FORMAT_BC4_UNORM + || format == DXGI_FORMAT_BC4_SNORM) ? 8 : 16; + + assert(nbw == layout.Plane[0].MipLayout[level].WidthElements); + assert(nbh == layout.Plane[0].MipLayout[level].HeightElements); + assert(bpb == layout.Plane[0].BytesPerElement); + + return DetileByElement2D(xbox, level, computer, layout, result, nimages, bpb, nbw, nbh); + } + else if (IsTypeless(format)) + { + //--- Typeless is done with per-element copy ---------------------------------- + size_t bpp = (BitsPerPixel(format) + 7) / 8; + + size_t w = result[0]->width; + size_t h = result[0]->height; + + assert(bpp == layout.Plane[0].BytesPerElement); + assert(w == layout.Plane[0].MipLayout[level].WidthElements); + assert(h == layout.Plane[0].MipLayout[level].HeightElements); + + return DetileByElement2D(xbox, level, computer, layout, result, nimages, bpp, w, h); + } + else + { + //--- Standard format handling ------------------------------------------------ + auto& mip = layout.Plane[0].MipLayout[level]; + + const size_t tiledPixels = mip.PaddedWidthElements * mip.PaddedHeightElements * mip.PaddedDepthOrArraySize; + + ScopedAlignedArrayXMVECTOR scanline( + reinterpret_cast(_aligned_malloc( + sizeof(XMVECTOR) * (tiledPixels + result[0]->width), 16))); + + XMVECTOR* target = scanline.get(); + XMVECTOR* tiled = target + result[0]->width; + +#ifdef _DEBUG + memset(target, 0xCD, sizeof(XMVECTOR) * result[0]->width); + memset(tiled, 0xDD, sizeof(XMVECTOR) * tiledPixels); +#endif + + // Load tiled texture + if ((xbox.GetSize() - mip.OffsetBytes) < mip.SizeBytes) + return E_FAIL; + + if (!_LoadScanline(tiled, tiledPixels, xbox.GetPointer() + mip.OffsetBytes, mip.SizeBytes, xbox.GetMetadata().format)) + return E_FAIL; + + // Perform detiling + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = result[item]; + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == result[0]->width); + assert(img->height == result[0]->height); + assert(img->rowPitch == result[0]->rowPitch); + assert(img->format == result[0]->format); + + auto dptr = reinterpret_cast(img->pixels); + for (uint32_t y = 0; y < img->height; ++y) + { + for (size_t x = 0; x < img->width; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, item, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + offset = (offset - mip.OffsetBytes) / layout.Plane[0].BytesPerElement; + assert(offset < tiledPixels); + + target[x] = tiled[offset]; + } + + if (!_StoreScanline(dptr, img->rowPitch, img->format, target, img->width)) + return E_FAIL; + + dptr += img->rowPitch; + } + } + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // 3D Tiling + //------------------------------------------------------------------------------------- + HRESULT Detile3D( + const XboxImage& xbox, + uint32_t level, + uint32_t slices, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const Image& result) + { + if (!computer || !xbox.GetPointer() || !result.pixels) + return E_POINTER; + + assert(xbox.GetMetadata().format == result.format); + + assert(layout.Planes == 1); + + if (IsCompressed(result.format)) + { + //--- BC formats use per-block copy ------------------------------------------- + size_t nbw = std::max(1, (result.width + 3) / 4); + size_t nbh = std::max(1, (result.height + 3) / 4); + + size_t bpb = (result.format == DXGI_FORMAT_BC1_TYPELESS + || result.format == DXGI_FORMAT_BC1_UNORM + || result.format == DXGI_FORMAT_BC1_UNORM_SRGB + || result.format == DXGI_FORMAT_BC4_TYPELESS + || result.format == DXGI_FORMAT_BC4_UNORM + || result.format == DXGI_FORMAT_BC4_SNORM) ? 8 : 16; + + assert(nbw == layout.Plane[0].MipLayout[level].WidthElements); + assert(nbh == layout.Plane[0].MipLayout[level].HeightElements); + assert(bpb == layout.Plane[0].BytesPerElement); + + return DetileByElement3D(xbox, level, slices, computer, layout, result, bpb, nbw, nbh); + } + else if (IsTypeless(result.format)) + { + //--- Typeless is done with per-element copy ---------------------------------- + size_t bpp = (BitsPerPixel(result.format) + 7) / 8; + + assert(bpp == layout.Plane[0].BytesPerElement); + assert(result.width == layout.Plane[0].MipLayout[level].WidthElements); + assert(result.height == layout.Plane[0].MipLayout[level].HeightElements); + + return DetileByElement3D(xbox, level, slices, computer, layout, result, bpp, result.width, result.height); + } + else + { + //--- Standard format handling ------------------------------------------------ + auto& mip = layout.Plane[0].MipLayout[level]; + + const size_t tiledPixels = mip.PaddedWidthElements * mip.PaddedHeightElements * mip.PaddedDepthOrArraySize; + assert(tiledPixels >= (result.width * result.height * slices)); + + ScopedAlignedArrayXMVECTOR scanline( + reinterpret_cast(_aligned_malloc( + sizeof(XMVECTOR) * (tiledPixels + result.width), 16))); + + XMVECTOR* target = scanline.get(); + XMVECTOR* tiled = target + result.width; + +#ifdef _DEBUG + memset(target, 0xCD, sizeof(XMVECTOR) * result.width); + memset(tiled, 0xDD, sizeof(XMVECTOR) * tiledPixels); +#endif + + // Load tiled texture + if ((xbox.GetSize() - mip.OffsetBytes) < mip.SizeBytes) + return E_FAIL; + + const uint8_t* sptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = sptr + mip.SizeBytes; + XMVECTOR* tptr = tiled; + for (uint32_t z = 0; z < mip.PaddedDepthOrArraySize; ++z) + { + const uint8_t* rptr = sptr; + XMVECTOR* uptr = tptr; + + for (uint32_t y = 0; y < mip.PaddedHeightElements; ++y) + { + if ((rptr + mip.PitchBytes) > endPtr) + return E_FAIL; + + if (!_LoadScanline(uptr, mip.PitchPixels, rptr, mip.PitchBytes, xbox.GetMetadata().format)) + return E_FAIL; + + rptr += mip.PitchBytes; + uptr += mip.PaddedWidthElements; + } + + sptr += mip.Slice2DSizeBytes; + tptr += mip.PaddedHeightElements * mip.PaddedWidthElements; + } + + // Perform detiling + uint8_t* dptr = reinterpret_cast(result.pixels); + for (uint32_t z = 0; z < slices; ++z) + { + uint8_t* rptr = dptr; + + for (uint32_t y = 0; y < result.height; ++y) + { + for (size_t x = 0; x < result.width; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, z, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + offset = (offset - mip.OffsetBytes) / layout.Plane[0].BytesPerElement; + assert(offset < tiledPixels); + + target[x] = tiled[offset]; + } + + if (!_StoreScanline(rptr, result.rowPitch, result.format, target, result.width)) + return E_FAIL; + + rptr += result.rowPitch; + } + + dptr += result.slicePitch; + } + } + + return S_OK; + } +} + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Detile image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::Detile( + const XboxImage& xbox, + DirectX::ScratchImage& image) +{ + if (!xbox.GetSize() || !xbox.GetPointer() || xbox.GetTileMode() == XG_TILE_MODE_INVALID) + return E_INVALIDARG; + + image.Release(); + + auto& metadata = xbox.GetMetadata(); + + if (metadata.format == DXGI_FORMAT_R1_UNORM + || IsVideo(metadata.format)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + switch (metadata.format) + { + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + default: + break; + } + + XG_RESOURCE_LAYOUT layout = {}; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + { + XG_TEXTURE1D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = static_cast(metadata.format); + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.MiscFlags = (metadata.IsCubemap()) ? XG_RESOURCE_MISC_TEXTURECUBE : 0; + desc.TileMode = xbox.GetTileMode(); + + ComPtr computer; + HRESULT hr = XGCreateTexture1DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (layout.SizeBytes != xbox.GetSize() + || layout.BaseAlignmentBytes != xbox.GetAlignment()) + return E_UNEXPECTED; + + hr = image.Initialize(metadata); + if (FAILED(hr)) + return hr; + + for (uint32_t level = 0; level < metadata.mipLevels; ++level) + { + if (metadata.arraySize > 1) + { + std::vector images; + images.reserve(metadata.arraySize); + for (uint32_t item = 0; item < metadata.arraySize; ++item) + { + const Image* img = image.GetImage(level, item, 0); + if (!img) + { + image.Release(); + return E_FAIL; + } + + images.push_back(img); + } + + hr = Detile1D(xbox, level, computer.Get(), layout, &images[0], images.size()); + } + else + { + const Image* img = image.GetImage(level, 0, 0); + if (!img) + { + image.Release(); + return E_FAIL; + } + + hr = Detile1D(xbox, level, computer.Get(), layout, &img, 1); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + } + } + break; + + case TEX_DIMENSION_TEXTURE2D: + { + XG_TEXTURE2D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = static_cast(metadata.format); + desc.SampleDesc.Count = 1; + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.MiscFlags = (metadata.miscFlags & TEX_MISC_TEXTURECUBE) ? XG_RESOURCE_MISC_TEXTURECUBE : 0; + desc.TileMode = xbox.GetTileMode(); + + ComPtr computer; + HRESULT hr = XGCreateTexture2DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (layout.SizeBytes != xbox.GetSize() + || layout.BaseAlignmentBytes != xbox.GetAlignment()) + return E_UNEXPECTED; + + hr = image.Initialize(metadata); + if (FAILED(hr)) + return hr; + + for (uint32_t level = 0; level < metadata.mipLevels; ++level) + { + if (metadata.arraySize > 1) + { + std::vector images; + images.reserve(metadata.arraySize); + for (uint32_t item = 0; item < metadata.arraySize; ++item) + { + const Image* img = image.GetImage(level, item, 0); + if (!img) + { + image.Release(); + return E_FAIL; + } + + images.push_back(img); + } + + hr = Detile2D(xbox, level, computer.Get(), layout, &images[0], images.size()); + } + else + { + const Image* img = image.GetImage(level, 0, 0); + if (!img) + { + image.Release(); + return E_FAIL; + } + + hr = Detile2D(xbox, level, computer.Get(), layout, &img, 1); + } + + if (FAILED(hr)) + { + image.Release(); + return hr; + } + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + XG_TEXTURE3D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.Depth = static_cast(metadata.depth); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.Format = static_cast(metadata.format); + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.TileMode = xbox.GetTileMode(); + + ComPtr computer; + HRESULT hr = XGCreateTexture3DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (layout.SizeBytes != xbox.GetSize() + || layout.BaseAlignmentBytes != xbox.GetAlignment()) + return E_UNEXPECTED; + + hr = image.Initialize(metadata); + if (FAILED(hr)) + return hr; + + uint32_t d = static_cast(metadata.depth); + + size_t index = 0; + for (uint32_t level = 0; level < metadata.mipLevels; ++level) + { + if ((index + d) > image.GetImageCount()) + { + image.Release(); + return E_FAIL; + } + + // Relies on the fact that slices are contiguous + hr = Detile3D(xbox, level, d, computer.Get(), layout, image.GetImages()[index]); + if (FAILED(hr)) + { + image.Release(); + return hr; + } + + index += d; + + if (d > 1) + d >>= 1; + } + } + break; + + default: + return E_FAIL; + } + + return S_OK; +} + diff --git a/Kits/DirectXTex/DirectXTexXboxImage.cpp b/Kits/DirectXTex/DirectXTexXboxImage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..318018731c7089ed8aedae38f4276d3c467eb8ff --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXboxImage.cpp @@ -0,0 +1,277 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexXboxImage.cpp +// +// DirectXTex Auxillary functions for Xbox One texture blob +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "DirectXTexP.h" +#include "DirectXTexXbox.h" + +using namespace DirectX; +using namespace Xbox; + +// Sanity check XG library values against DirectXTex's values +static_assert( XG_FORMAT_UNKNOWN == DXGI_FORMAT_UNKNOWN , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32A32_TYPELESS == DXGI_FORMAT_R32G32B32A32_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32A32_FLOAT == DXGI_FORMAT_R32G32B32A32_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32A32_UINT == DXGI_FORMAT_R32G32B32A32_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32A32_SINT == DXGI_FORMAT_R32G32B32A32_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32_TYPELESS == DXGI_FORMAT_R32G32B32_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32_FLOAT == DXGI_FORMAT_R32G32B32_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32_UINT == DXGI_FORMAT_R32G32B32_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32B32_SINT == DXGI_FORMAT_R32G32B32_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16B16A16_TYPELESS == DXGI_FORMAT_R16G16B16A16_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16B16A16_FLOAT == DXGI_FORMAT_R16G16B16A16_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16B16A16_UNORM == DXGI_FORMAT_R16G16B16A16_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16B16A16_UINT == DXGI_FORMAT_R16G16B16A16_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16B16A16_SNORM == DXGI_FORMAT_R16G16B16A16_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16B16A16_SINT == DXGI_FORMAT_R16G16B16A16_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32_TYPELESS == DXGI_FORMAT_R32G32_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32_FLOAT == DXGI_FORMAT_R32G32_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32_UINT == DXGI_FORMAT_R32G32_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G32_SINT == DXGI_FORMAT_R32G32_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32G8X24_TYPELESS == DXGI_FORMAT_R32G8X24_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_D32_FLOAT_S8X24_UINT == DXGI_FORMAT_D32_FLOAT_S8X24_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32_FLOAT_X8X24_TYPELESS == DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_X32_TYPELESS_G8X24_UINT == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R10G10B10A2_TYPELESS == DXGI_FORMAT_R10G10B10A2_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R10G10B10A2_UNORM == DXGI_FORMAT_R10G10B10A2_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R10G10B10A2_UINT == DXGI_FORMAT_R10G10B10A2_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R11G11B10_FLOAT == DXGI_FORMAT_R11G11B10_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8B8A8_TYPELESS == DXGI_FORMAT_R8G8B8A8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8B8A8_UNORM == DXGI_FORMAT_R8G8B8A8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8B8A8_UNORM_SRGB == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8B8A8_UINT == DXGI_FORMAT_R8G8B8A8_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8B8A8_SNORM == DXGI_FORMAT_R8G8B8A8_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8B8A8_SINT == DXGI_FORMAT_R8G8B8A8_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16_TYPELESS == DXGI_FORMAT_R16G16_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16_FLOAT == DXGI_FORMAT_R16G16_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16_UNORM == DXGI_FORMAT_R16G16_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16_UINT == DXGI_FORMAT_R16G16_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16_SNORM == DXGI_FORMAT_R16G16_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16G16_SINT == DXGI_FORMAT_R16G16_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32_TYPELESS == DXGI_FORMAT_R32_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_D32_FLOAT == DXGI_FORMAT_D32_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32_FLOAT == DXGI_FORMAT_R32_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32_UINT == DXGI_FORMAT_R32_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R32_SINT == DXGI_FORMAT_R32_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R24G8_TYPELESS == DXGI_FORMAT_R24G8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_D24_UNORM_S8_UINT == DXGI_FORMAT_D24_UNORM_S8_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R24_UNORM_X8_TYPELESS == DXGI_FORMAT_R24_UNORM_X8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_X24_TYPELESS_G8_UINT == DXGI_FORMAT_X24_TYPELESS_G8_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8_TYPELESS == DXGI_FORMAT_R8G8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8_UNORM == DXGI_FORMAT_R8G8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8_UINT == DXGI_FORMAT_R8G8_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8_SNORM == DXGI_FORMAT_R8G8_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8_SINT == DXGI_FORMAT_R8G8_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16_TYPELESS == DXGI_FORMAT_R16_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16_FLOAT == DXGI_FORMAT_R16_FLOAT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_D16_UNORM == DXGI_FORMAT_D16_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16_UNORM == DXGI_FORMAT_R16_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16_UINT == DXGI_FORMAT_R16_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16_SNORM == DXGI_FORMAT_R16_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R16_SINT == DXGI_FORMAT_R16_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8_TYPELESS == DXGI_FORMAT_R8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8_UNORM == DXGI_FORMAT_R8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8_UINT == DXGI_FORMAT_R8_UINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8_SNORM == DXGI_FORMAT_R8_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8_SINT == DXGI_FORMAT_R8_SINT , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_A8_UNORM == DXGI_FORMAT_A8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R1_UNORM == DXGI_FORMAT_R1_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R9G9B9E5_SHAREDEXP == DXGI_FORMAT_R9G9B9E5_SHAREDEXP , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R8G8_B8G8_UNORM == DXGI_FORMAT_R8G8_B8G8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_G8R8_G8B8_UNORM == DXGI_FORMAT_G8R8_G8B8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC1_TYPELESS == DXGI_FORMAT_BC1_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC1_UNORM == DXGI_FORMAT_BC1_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC1_UNORM_SRGB == DXGI_FORMAT_BC1_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC2_TYPELESS == DXGI_FORMAT_BC2_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC2_UNORM == DXGI_FORMAT_BC2_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC2_UNORM_SRGB == DXGI_FORMAT_BC2_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC3_TYPELESS == DXGI_FORMAT_BC3_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC3_UNORM == DXGI_FORMAT_BC3_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC3_UNORM_SRGB == DXGI_FORMAT_BC3_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC4_TYPELESS == DXGI_FORMAT_BC4_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC4_UNORM == DXGI_FORMAT_BC4_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC4_SNORM == DXGI_FORMAT_BC4_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC5_TYPELESS == DXGI_FORMAT_BC5_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC5_UNORM == DXGI_FORMAT_BC5_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC5_SNORM == DXGI_FORMAT_BC5_SNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B5G6R5_UNORM == DXGI_FORMAT_B5G6R5_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B5G5R5A1_UNORM == DXGI_FORMAT_B5G5R5A1_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B8G8R8A8_UNORM == DXGI_FORMAT_B8G8R8A8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B8G8R8X8_UNORM == DXGI_FORMAT_B8G8R8X8_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_R10G10B10_XR_BIAS_A2_UNORM == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B8G8R8A8_TYPELESS == DXGI_FORMAT_B8G8R8A8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B8G8R8A8_UNORM_SRGB == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B8G8R8X8_TYPELESS == DXGI_FORMAT_B8G8R8X8_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B8G8R8X8_UNORM_SRGB == DXGI_FORMAT_B8G8R8X8_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC6H_TYPELESS == DXGI_FORMAT_BC6H_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC6H_UF16 == DXGI_FORMAT_BC6H_UF16 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC6H_SF16 == DXGI_FORMAT_BC6H_SF16 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC7_TYPELESS == DXGI_FORMAT_BC7_TYPELESS , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC7_UNORM == DXGI_FORMAT_BC7_UNORM , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_BC7_UNORM_SRGB == DXGI_FORMAT_BC7_UNORM_SRGB , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_AYUV == DXGI_FORMAT_AYUV , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_Y410 == DXGI_FORMAT_Y410 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_Y416 == DXGI_FORMAT_Y416 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_NV12 == DXGI_FORMAT_NV12 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_P010 == DXGI_FORMAT_P010 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_P016 == DXGI_FORMAT_P016 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_420_OPAQUE == DXGI_FORMAT_420_OPAQUE , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_YUY2 == DXGI_FORMAT_YUY2 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_Y210 == DXGI_FORMAT_Y210 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_Y216 == DXGI_FORMAT_Y216 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_NV11 == DXGI_FORMAT_NV11 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_AI44 == DXGI_FORMAT_AI44 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_IA44 == DXGI_FORMAT_IA44 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_P8 == DXGI_FORMAT_P8 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_A8P8 == DXGI_FORMAT_A8P8 , "XG vs. DXGI mismatch" ); +static_assert( XG_FORMAT_B4G4R4A4_UNORM == DXGI_FORMAT_B4G4R4A4_UNORM , "XG vs. DXGI mismatch" ); + +static_assert( XG_RESOURCE_DIMENSION_TEXTURE1D == TEX_DIMENSION_TEXTURE1D, "XG vs. Direct3D 11 mismatch" ); +static_assert( XG_RESOURCE_DIMENSION_TEXTURE2D == TEX_DIMENSION_TEXTURE2D, "XG vs. Direct3D 11 mismatch" ); +static_assert( XG_RESOURCE_DIMENSION_TEXTURE3D == TEX_DIMENSION_TEXTURE3D, "XG vs. Direct3D 11 mismatch" ); + +static_assert( XG_RESOURCE_MISC_TEXTURECUBE == TEX_MISC_TEXTURECUBE, "XG vs. Direct3D 11 mismatch" ); + +//-------------------------------------------------------------------------------------- +// Initialize memory +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT XboxImage::Initialize( const XG_TEXTURE1D_DESC& desc, const XG_RESOURCE_LAYOUT& layout, uint32_t miscFlags2 ) +{ + if ( !layout.SizeBytes || !layout.BaseAlignmentBytes ) + return E_INVALIDARG; + + Release(); + + if ( layout.SizeBytes > UINT32_MAX + || layout.BaseAlignmentBytes > UINT32_MAX ) + return E_FAIL; + + memory = reinterpret_cast( _aligned_malloc( layout.SizeBytes, 16 ) ); + if ( !memory ) + return E_OUTOFMEMORY; + + memset( &metadata, 0, sizeof(metadata) ); + metadata.width = desc.Width; + metadata.height = 1; + metadata.depth = 1; + metadata.arraySize = desc.ArraySize; + metadata.mipLevels = layout.MipLevels; + metadata.format = static_cast( desc.Format ); + metadata.dimension = TEX_DIMENSION_TEXTURE1D; + metadata.miscFlags2 = miscFlags2; + + dataSize = static_cast( layout.SizeBytes ); + baseAlignment = static_cast( layout.BaseAlignmentBytes ); + tilemode = desc.TileMode; + + return S_OK; +} + + +_Use_decl_annotations_ +HRESULT XboxImage::Initialize( const XG_TEXTURE2D_DESC& desc, const XG_RESOURCE_LAYOUT& layout, uint32_t miscFlags2 ) +{ + if ( !layout.SizeBytes || !layout.BaseAlignmentBytes ) + return E_INVALIDARG; + + Release(); + + if ( layout.SizeBytes > UINT32_MAX + || layout.BaseAlignmentBytes > UINT32_MAX ) + return E_FAIL; + + memory = reinterpret_cast( _aligned_malloc( layout.SizeBytes, 16 ) ); + if ( !memory ) + return E_OUTOFMEMORY; + + memset( &metadata, 0, sizeof(metadata) ); + metadata.width = desc.Width; + metadata.height = desc.Height; + metadata.depth = 1; + metadata.arraySize = desc.ArraySize; + metadata.mipLevels = layout.MipLevels; + metadata.miscFlags = (desc.MiscFlags & XG_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0; + metadata.format = static_cast( desc.Format ); + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + metadata.miscFlags2 = miscFlags2; + + dataSize = static_cast( layout.SizeBytes ); + baseAlignment = static_cast( layout.BaseAlignmentBytes ); + tilemode = desc.TileMode; + + return S_OK; +} + + +_Use_decl_annotations_ +HRESULT XboxImage::Initialize( const XG_TEXTURE3D_DESC& desc, const XG_RESOURCE_LAYOUT& layout, uint32_t miscFlags2 ) +{ + if ( !layout.SizeBytes || !layout.BaseAlignmentBytes ) + return E_INVALIDARG; + + Release(); + + if ( layout.SizeBytes > UINT32_MAX + || layout.BaseAlignmentBytes > UINT32_MAX ) + return E_FAIL; + + memory = reinterpret_cast( _aligned_malloc( layout.SizeBytes, 16 ) ); + if ( !memory ) + return E_OUTOFMEMORY; + + memset( &metadata, 0, sizeof(metadata) ); + metadata.width = desc.Width; + metadata.height = desc.Height; + metadata.depth = desc.Depth; + metadata.arraySize = 1; + metadata.mipLevels = layout.MipLevels; + metadata.format = static_cast( desc.Format ); + metadata.dimension = TEX_DIMENSION_TEXTURE3D; + metadata.miscFlags2 = miscFlags2; + + dataSize = static_cast( layout.SizeBytes ); + baseAlignment = static_cast( layout.BaseAlignmentBytes ); + tilemode = desc.TileMode; + + return S_OK; +} + + +_Use_decl_annotations_ +HRESULT XboxImage::Initialize( const DirectX::TexMetadata& mdata, XG_TILE_MODE tm, uint32_t size, uint32_t alignment ) +{ + if ( !size || !alignment || tm == XG_TILE_MODE_INVALID ) + return E_INVALIDARG; + + Release(); + + memory = reinterpret_cast( _aligned_malloc( size, 16 ) ); + if ( !memory ) + return E_OUTOFMEMORY; + + metadata = mdata; + + dataSize = size; + baseAlignment = alignment; + tilemode = tm; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Release memory +//-------------------------------------------------------------------------------------- +void XboxImage::Release() +{ + if ( memory ) + { + _aligned_free( memory ); + memory = nullptr; + } +} diff --git a/Kits/DirectXTex/DirectXTexXboxTile.cpp b/Kits/DirectXTex/DirectXTexXboxTile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b153591f9c68efff3342f27ba97ecd37057eeaa --- /dev/null +++ b/Kits/DirectXTex/DirectXTexXboxTile.cpp @@ -0,0 +1,898 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexXboxTile.cpp +// +// DirectXTex Auxillary functions for converting from linear to Xbox One tiling +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "DirectXTexP.h" +#include "DirectXTexXbox.h" + +//#define VERBOSE + +using Microsoft::WRL::ComPtr; +using namespace DirectX; +using namespace Xbox; + +namespace +{ + //---------------------------------------------------------------------------------- + inline HRESULT TileByElement1D( + _In_reads_(nimages) const Image** images, + size_t nimages, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + _In_ const XG_RESOURCE_LAYOUT& layout, + const XboxImage& xbox, + size_t bpp, + size_t w) + { + auto& mip = layout.Plane[0].MipLayout[level]; + + uint8_t* dptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = dptr + mip.SizeBytes; + + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = images[item]; + + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == images[0]->width); + assert(img->height == images[0]->height); + assert(img->rowPitch == images[0]->rowPitch); + assert(img->format == images[0]->format); + + const uint8_t* sptr = img->pixels; + + for (size_t x = 0; x < w; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, 0, item, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + uint8_t* dest = dptr + offset - mip.OffsetBytes; + + if ((dest + bpp) > endPtr) + return E_FAIL; + + memcpy(dest, sptr, bpp); + sptr += bpp; + } + } + + return S_OK; + } + + //---------------------------------------------------------------------------------- + inline HRESULT TileByElement2D( + _In_reads_(nimages) const Image** images, + size_t nimages, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const XboxImage& xbox, + size_t bpp, + size_t w, + size_t h) + { + auto& mip = layout.Plane[0].MipLayout[level]; + + uint8_t* dptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = dptr + mip.SizeBytes; + + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = images[item]; + + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == images[0]->width); + assert(img->height == images[0]->height); + assert(img->rowPitch == images[0]->rowPitch); + assert(img->format == images[0]->format); + + const uint8_t* sptr = img->pixels; + for (uint32_t y = 0; y < h; ++y) + { + const uint8_t* tptr = sptr; + + for (size_t x = 0; x < w; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, item, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + uint8_t* dest = dptr + offset - mip.OffsetBytes; + + if ((dest + bpp) > endPtr) + return E_FAIL; + + memcpy(dest, tptr, bpp); + tptr += bpp; + } + + sptr += img->rowPitch; + } + } + + return S_OK; + } + + //---------------------------------------------------------------------------------- + inline HRESULT TileByElement3D( + const Image& image, + uint32_t level, + uint32_t slices, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const XboxImage& xbox, + size_t bpp, + size_t w, + size_t h) + { + auto& mip = layout.Plane[0].MipLayout[level]; + + uint8_t* dptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = dptr + mip.SizeBytes; + + const uint8_t* sptr = image.pixels; + for (uint32_t z = 0; z < slices; ++z) + { + const uint8_t* rptr = sptr; + + for (uint32_t y = 0; y < h; ++y) + { + const uint8_t* tptr = rptr; + + for (size_t x = 0; x < w; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, z, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + uint8_t* dest = dptr + offset - mip.OffsetBytes; + + if ((dest + bpp) > endPtr) + return E_FAIL; + + memcpy(dest, tptr, bpp); + tptr += bpp; + } + + rptr += image.rowPitch; + } + + sptr += image.slicePitch; + } + + return S_OK; + } + + //---------------------------------------------------------------------------------- +#ifdef VERBOSE + void DebugPrintLayout(const XG_RESOURCE_LAYOUT& layout) + { + wchar_t buff[2048]; + + swprintf_s(buff, L"Layout %u planes, %uD, %u mips, %I64u size, %I64u alignment\n", layout.Planes, layout.Dimension - 1, layout.MipLevels, layout.SizeBytes, layout.BaseAlignmentBytes); + OutputDebugStringW(buff); + + for (size_t p = 0; p < layout.Planes; ++p) + { + auto& plane = layout.Plane[p]; + + swprintf_s(buff, L"Plane %Iu: %u bpe, %I64u size, %I64u offset, %I64u alignment\n", p, plane.BytesPerElement, plane.SizeBytes, plane.BaseOffsetBytes, plane.BaseAlignmentBytes); + OutputDebugStringW(buff); + + for (size_t level = 0; level < layout.MipLevels; ++level) + { + auto& mip = plane.MipLayout[level]; + + swprintf_s(buff, L"\tLevel %Iu: %I64u size, %I64u slice2D, %I64u offset, %u alignment\n", level, mip.SizeBytes, mip.Slice2DSizeBytes, mip.OffsetBytes, mip.AlignmentBytes); + OutputDebugStringW(buff); + + swprintf_s(buff, L"\t\t%u x %u x %u (padded %u x %u x %u)\n", mip.WidthElements, mip.HeightElements, mip.DepthOrArraySize, + mip.PaddedWidthElements, mip.PaddedHeightElements, mip.PaddedDepthOrArraySize); + OutputDebugStringW(buff); + + swprintf_s(buff, L"\t\tpitch %u pixels (%u bytes)\n", mip.PitchPixels, mip.PitchBytes); + OutputDebugStringW(buff); + + swprintf_s(buff, L"\t\t\t%u samples, %u tilemode\n", mip.SampleCount, mip.TileMode); + OutputDebugStringW(buff); + } + } + } +#endif + + //------------------------------------------------------------------------------------- + // 1D Tiling + //------------------------------------------------------------------------------------- + HRESULT Tile1D( + _In_reads_(nimages) const Image** images, + size_t nimages, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const XboxImage& xbox) + { + if (!nimages) + return E_INVALIDARG; + + if (!images || !images[0] || !computer || !xbox.GetPointer()) + return E_POINTER; + + assert(layout.Planes == 1); + + DXGI_FORMAT format = images[0]->format; + + assert(format == xbox.GetMetadata().format); + + assert(!IsCompressed(format)); + + if (IsTypeless(format)) + { + //--- Typeless is done with per-element copy ---------------------------------- + size_t bpp = (BitsPerPixel(format) + 7) / 8; + size_t w = images[0]->width; + + assert(bpp == layout.Plane[0].BytesPerElement); + assert(w == layout.Plane[0].MipLayout[level].WidthElements); + + return TileByElement1D(images, nimages, level, computer, layout, xbox, bpp, w); + } + else + { + //--- Standard format handling ------------------------------------------------ + auto& mip = layout.Plane[0].MipLayout[level]; + + size_t tiledPixels = mip.PitchPixels * mip.PaddedDepthOrArraySize; + + ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast( + _aligned_malloc(sizeof(XMVECTOR) * (images[0]->width + (tiledPixels)), 16))); + + XMVECTOR* row = scanline.get(); + XMVECTOR* tiled = row + images[0]->width; + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR) * images[0]->width); +#endif + + memset(tiled, 0, sizeof(XMVECTOR) * tiledPixels); + + // Perform tiling + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = images[item]; + + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == images[0]->width); + assert(img->height == images[0]->height); + assert(img->rowPitch == images[0]->rowPitch); + assert(img->format == images[0]->format); + + if (!_LoadScanline(row, img->width, img->pixels, img->rowPitch, img->format)) + return E_FAIL; + + for (size_t x = 0; x < img->width; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, 0, item, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + offset = (offset - mip.OffsetBytes) / layout.Plane[0].BytesPerElement; + assert(offset < tiledPixels); + + tiled[offset] = row[x]; + } + } + + // Store tiled texture + if (!_StoreScanline(xbox.GetPointer() + mip.OffsetBytes, mip.SizeBytes, xbox.GetMetadata().format, tiled, tiledPixels)) + return E_FAIL; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // 2D Tiling + //------------------------------------------------------------------------------------- + HRESULT Tile2D( + _In_reads_(nimages) const Image** images, + size_t nimages, + uint32_t level, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const XboxImage& xbox) + { + if (!nimages) + return E_INVALIDARG; + + if (!images || !images[0] || !computer || !xbox.GetPointer()) + return E_POINTER; + + assert(layout.Planes == 1); + + DXGI_FORMAT format = images[0]->format; + + assert(format == xbox.GetMetadata().format); + + if (IsCompressed(format)) + { + //--- BC formats use per-block copy ------------------------------------------- + size_t nbw = std::max(1, (images[0]->width + 3) / 4); + size_t nbh = std::max(1, (images[0]->height + 3) / 4); + + size_t bpb = (format == DXGI_FORMAT_BC1_TYPELESS + || format == DXGI_FORMAT_BC1_UNORM + || format == DXGI_FORMAT_BC1_UNORM_SRGB + || format == DXGI_FORMAT_BC4_TYPELESS + || format == DXGI_FORMAT_BC4_UNORM + || format == DXGI_FORMAT_BC4_SNORM) ? 8 : 16; + + assert(nbw == layout.Plane[0].MipLayout[level].WidthElements); + assert(nbh == layout.Plane[0].MipLayout[level].HeightElements); + assert(bpb == layout.Plane[0].BytesPerElement); + + return TileByElement2D(images, nimages, level, computer, layout, xbox, bpb, nbw, nbh); + } + else if (IsTypeless(format)) + { + //--- Typeless is done with per-element copy ---------------------------------- + size_t bpp = (BitsPerPixel(format) + 7) / 8; + + size_t w = images[0]->width; + size_t h = images[0]->height; + + assert(bpp == layout.Plane[0].BytesPerElement); + assert(w == layout.Plane[0].MipLayout[level].WidthElements); + assert(h == layout.Plane[0].MipLayout[level].HeightElements); + + return TileByElement2D(images, nimages, level, computer, layout, xbox, bpp, w, h); + } + else + { + //--- Standard format handling ------------------------------------------------ + auto& mip = layout.Plane[0].MipLayout[level]; + + const size_t tiledPixels = mip.PaddedWidthElements * mip.PaddedHeightElements * mip.PaddedDepthOrArraySize; + + ScopedAlignedArrayXMVECTOR scanline( + reinterpret_cast(_aligned_malloc( + sizeof(XMVECTOR) * (images[0]->width + tiledPixels), 16))); + + XMVECTOR* row = scanline.get(); + XMVECTOR* tiled = row + images[0]->width; + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR) * images[0]->width); +#endif + + memset(tiled, 0, sizeof(XMVECTOR) * tiledPixels); + + // Perform tiling + for (uint32_t item = 0; item < nimages; ++item) + { + const Image* img = images[item]; + + if (!img || !img->pixels) + return E_POINTER; + + assert(img->width == images[0]->width); + assert(img->height == images[0]->height); + assert(img->rowPitch == images[0]->rowPitch); + assert(img->format == images[0]->format); + + auto sptr = reinterpret_cast(img->pixels); + for (uint32_t y = 0; y < img->height; ++y) + { + if (!_LoadScanline(row, img->width, sptr, img->rowPitch, img->format)) + return E_FAIL; + + sptr += img->rowPitch; + + for (size_t x = 0; x < img->width; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, item, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + offset = (offset - mip.OffsetBytes) / layout.Plane[0].BytesPerElement; + assert(offset < tiledPixels); + + tiled[offset] = row[x]; + } + } + } + + // Store tiled texture + if (!_StoreScanline(xbox.GetPointer() + mip.OffsetBytes, mip.SizeBytes, xbox.GetMetadata().format, tiled, tiledPixels)) + return E_FAIL; + } + + return S_OK; + } + + + //------------------------------------------------------------------------------------- + // 3D Tiling + //------------------------------------------------------------------------------------- + HRESULT Tile3D( + const Image& image, + uint32_t level, + uint32_t slices, + _In_ XGTextureAddressComputer* computer, + const XG_RESOURCE_LAYOUT& layout, + const XboxImage& xbox) + { + if (!image.pixels || !computer || !xbox.GetPointer()) + return E_POINTER; + + assert(slices > 0); + + assert(layout.Planes == 1); + + assert(image.format == xbox.GetMetadata().format); + + if (IsCompressed(image.format)) + { + //--- BC formats use per-block copy ------------------------------------------- + size_t nbw = std::max(1, (image.width + 3) / 4); + size_t nbh = std::max(1, (image.height + 3) / 4); + + size_t bpb = (image.format == DXGI_FORMAT_BC1_TYPELESS + || image.format == DXGI_FORMAT_BC1_UNORM + || image.format == DXGI_FORMAT_BC1_UNORM_SRGB + || image.format == DXGI_FORMAT_BC4_TYPELESS + || image.format == DXGI_FORMAT_BC4_UNORM + || image.format == DXGI_FORMAT_BC4_SNORM) ? 8 : 16; + + assert(nbw == layout.Plane[0].MipLayout[level].WidthElements); + assert(nbh == layout.Plane[0].MipLayout[level].HeightElements); + assert(bpb == layout.Plane[0].BytesPerElement); + + return TileByElement3D(image, level, slices, computer, layout, xbox, bpb, nbw, nbh); + } + else if (IsTypeless(image.format)) + { + //--- Typeless is done with per-element copy ---------------------------------- + size_t bpp = (BitsPerPixel(image.format) + 7) / 8; + + assert(bpp == layout.Plane[0].BytesPerElement); + assert(image.width == layout.Plane[0].MipLayout[level].WidthElements); + assert(image.height == layout.Plane[0].MipLayout[level].HeightElements); + + return TileByElement3D(image, level, slices, computer, layout, xbox, bpp, image.width, image.height); + } + else + { + //--- Standard format handling ------------------------------------------------ + auto& mip = layout.Plane[0].MipLayout[level]; + + const size_t tiledPixels = mip.PaddedWidthElements * mip.PaddedHeightElements * mip.PaddedDepthOrArraySize; + assert(tiledPixels >= (image.width * image.height * slices)); + + ScopedAlignedArrayXMVECTOR scanline( + reinterpret_cast(_aligned_malloc( + sizeof(XMVECTOR) * (image.width + tiledPixels), 16))); + + XMVECTOR* row = scanline.get(); + XMVECTOR* tiled = row + image.width; + +#ifdef _DEBUG + memset(row, 0xCD, sizeof(XMVECTOR) * image.width); +#endif + + memset(tiled, 0, sizeof(XMVECTOR) * tiledPixels); + + // Perform tiling + const uint8_t* sptr = reinterpret_cast(image.pixels); + for (uint32_t z = 0; z < slices; ++z) + { + const uint8_t* rptr = sptr; + + for (uint32_t y = 0; y < image.height; ++y) + { + if (!_LoadScanline(row, image.width, rptr, image.rowPitch, image.format)) + return E_FAIL; + + rptr += image.rowPitch; + + for (size_t x = 0; x < image.width; ++x) + { + size_t offset = computer->GetTexelElementOffsetBytes(0, level, x, y, z, 0); + assert(offset >= mip.OffsetBytes); + assert(offset < mip.OffsetBytes + mip.SizeBytes); + + offset = (offset - mip.OffsetBytes) / layout.Plane[0].BytesPerElement; + assert(offset < tiledPixels); + + tiled[offset] = row[x]; + } + } + + sptr += image.slicePitch; + } + + // Store tiled texture + uint8_t* dptr = xbox.GetPointer() + mip.OffsetBytes; + const uint8_t* endPtr = dptr + mip.SizeBytes; + const XMVECTOR* tptr = tiled; + for (uint32_t z = 0; z < mip.PaddedDepthOrArraySize; ++z) + { + uint8_t* rptr = dptr; + const XMVECTOR* uptr = tptr; + + for (uint32_t y = 0; y < mip.PaddedHeightElements; ++y) + { + if ((rptr + mip.PitchBytes) > endPtr) + return E_FAIL; + + if (!_StoreScanline(rptr, mip.PitchBytes, xbox.GetMetadata().format, uptr, mip.PitchPixels)) + return E_FAIL; + + rptr += mip.PitchBytes; + uptr += mip.PaddedWidthElements; + } + + dptr += mip.Slice2DSizeBytes; + tptr += mip.PaddedHeightElements * mip.PaddedWidthElements; + } + } + + return S_OK; + } +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Tile image +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::Tile( + const DirectX::Image& srcImage, + XboxImage& xbox, + XG_TILE_MODE mode) +{ + if (!srcImage.pixels + || srcImage.width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION + || srcImage.height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) + return E_INVALIDARG; + + xbox.Release(); + + if (srcImage.format == DXGI_FORMAT_R1_UNORM + || IsVideo(srcImage.format)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (mode == XG_TILE_MODE_INVALID) + { + // If no specific tile mode is given, assume the optimal default + mode = XGComputeOptimalTileMode(XG_RESOURCE_DIMENSION_TEXTURE2D, static_cast(srcImage.format), + static_cast(srcImage.width), static_cast(srcImage.height), + 1, 1, XG_BIND_SHADER_RESOURCE); + } + + XG_TEXTURE2D_DESC desc = {}; + desc.Width = static_cast(srcImage.width); + desc.Height = static_cast(srcImage.height); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = static_cast(srcImage.format); + desc.SampleDesc.Count = 1; + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.TileMode = mode; + + ComPtr computer; + HRESULT hr = XGCreateTexture2DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + XG_RESOURCE_LAYOUT layout; + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + hr = xbox.Initialize(desc, layout); + if (FAILED(hr)) + return hr; + + const Image* images = &srcImage; + hr = Tile2D(&images, 1, 0, computer.Get(), layout, xbox); + if (FAILED(hr)) + { + xbox.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Tile image (complex) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::Tile( + const DirectX::Image* srcImages, + size_t nimages, + const DirectX::TexMetadata& metadata, + XboxImage& xbox, + XG_TILE_MODE mode) +{ + if (!srcImages + || !nimages + || metadata.width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION + || metadata.height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION + || metadata.depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + || metadata.arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION + || metadata.mipLevels > D3D11_REQ_MIP_LEVELS) + return E_INVALIDARG; + + xbox.Release(); + + if (metadata.format == DXGI_FORMAT_R1_UNORM + || IsVideo(metadata.format)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + switch (metadata.format) + { + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + default: + break; + } + + if (mode == XG_TILE_MODE_INVALID) + { + // If no specific tile mode is given, assume the optimal default + mode = XGComputeOptimalTileMode(static_cast(metadata.dimension), static_cast(metadata.format), + static_cast(metadata.width), static_cast(metadata.height), + static_cast((metadata.dimension == TEX_DIMENSION_TEXTURE3D) ? metadata.depth : metadata.arraySize), + 1, XG_BIND_SHADER_RESOURCE); + } + + XG_RESOURCE_LAYOUT layout = {}; + + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + { + XG_TEXTURE1D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = static_cast(metadata.format); + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.MiscFlags = (metadata.IsCubemap()) ? XG_RESOURCE_MISC_TEXTURECUBE : 0; + desc.TileMode = mode; + + ComPtr computer; + HRESULT hr = XGCreateTexture1DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + +#ifdef VERBOSE + DebugPrintLayout(layout); +#endif + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + hr = xbox.Initialize(desc, layout, metadata.miscFlags2); + if (FAILED(hr)) + return hr; + + for (uint32_t level = 0; level < metadata.mipLevels; ++level) + { + if (metadata.arraySize > 1) + { + std::vector images; + images.reserve(metadata.arraySize); + for (uint32_t item = 0; item < metadata.arraySize; ++item) + { + size_t index = metadata.ComputeIndex(level, item, 0); + if (index >= nimages) + { + xbox.Release(); + return E_FAIL; + } + + images.push_back(&srcImages[index]); + } + + hr = Tile1D(&images[0], images.size(), level, computer.Get(), layout, xbox); + } + else + { + size_t index = metadata.ComputeIndex(level, 0, 0); + if (index >= nimages) + { + xbox.Release(); + return E_FAIL; + } + + const Image* images = &srcImages[index]; + hr = Tile1D(&images, 1, level, computer.Get(), layout, xbox); + } + + if (FAILED(hr)) + { + xbox.Release(); + return hr; + } + } + } + break; + + case TEX_DIMENSION_TEXTURE2D: + { + XG_TEXTURE2D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.ArraySize = static_cast(metadata.arraySize); + desc.Format = static_cast(metadata.format); + desc.SampleDesc.Count = 1; + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.MiscFlags = (metadata.miscFlags & TEX_MISC_TEXTURECUBE) ? XG_RESOURCE_MISC_TEXTURECUBE : 0; + desc.TileMode = mode; + + ComPtr computer; + HRESULT hr = XGCreateTexture2DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + +#ifdef VERBOSE + DebugPrintLayout(layout); +#endif + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + hr = xbox.Initialize(desc, layout, metadata.miscFlags2); + if (FAILED(hr)) + return hr; + + for (uint32_t level = 0; level < metadata.mipLevels; ++level) + { + if (metadata.arraySize > 1) + { + std::vector images; + images.reserve(metadata.arraySize); + for (uint32_t item = 0; item < metadata.arraySize; ++item) + { + size_t index = metadata.ComputeIndex(level, item, 0); + if (index >= nimages) + { + xbox.Release(); + return E_FAIL; + } + + images.push_back(&srcImages[index]); + } + + hr = Tile2D(&images[0], images.size(), level, computer.Get(), layout, xbox); + } + else + { + size_t index = metadata.ComputeIndex(level, 0, 0); + if (index >= nimages) + { + xbox.Release(); + return E_FAIL; + } + + const Image* images = &srcImages[index]; + hr = Tile2D(&images, 1, level, computer.Get(), layout, xbox); + } + + if (FAILED(hr)) + { + xbox.Release(); + return hr; + } + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + { + XG_TEXTURE3D_DESC desc = {}; + desc.Width = static_cast(metadata.width); + desc.Height = static_cast(metadata.height); + desc.Depth = static_cast(metadata.depth); + desc.MipLevels = static_cast(metadata.mipLevels); + desc.Format = static_cast(metadata.format); + desc.Usage = XG_USAGE_DEFAULT; + desc.BindFlags = XG_BIND_SHADER_RESOURCE; + desc.TileMode = mode; + + ComPtr computer; + HRESULT hr = XGCreateTexture3DComputer(&desc, computer.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = computer->GetResourceLayout(&layout); + if (FAILED(hr)) + return hr; + +#ifdef VERBOSE + DebugPrintLayout(layout); +#endif + + if (layout.Planes != 1) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + hr = xbox.Initialize(desc, layout, metadata.miscFlags2); + if (FAILED(hr)) + return hr; + + uint32_t d = static_cast(metadata.depth); + + size_t index = 0; + for (uint32_t level = 0; level < metadata.mipLevels; ++level) + { + if ((index + d) > nimages) + { + xbox.Release(); + return E_FAIL; + } + + // Relies on the fact that slices are contiguous + hr = Tile3D(srcImages[index], level, d, computer.Get(), layout, xbox); + if (FAILED(hr)) + { + xbox.Release(); + return hr; + } + + index += d; + + if (d > 1) + d >>= 1; + } + } + break; + + default: + return E_FAIL; + } + + return S_OK; +} + diff --git a/Kits/DirectXTex/DirectXTex_XboxOneXDK_PC_2015.vcxproj b/Kits/DirectXTex/DirectXTex_XboxOneXDK_PC_2015.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6f46fe6579cdceeaf743390b3ac4bba6c6084317 --- /dev/null +++ b/Kits/DirectXTex/DirectXTex_XboxOneXDK_PC_2015.vcxproj @@ -0,0 +1,284 @@ + + + + + Debug + x64 + + + Profile + x64 + + + Release + x64 + + + + DirectXTex + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34} + DirectXTex + Win32Proj + + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + + + + + + + + + + + + + Bin\XDKPC_2015\$(Platform)\$(Configuration)\ + Bin\XDKPC_2015\$(Platform)\$(Configuration)\ + DirectXTex + true + $(XboxOneXDKLatest)PC\include;$(DurangoXDK)PC\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(XboxOneXDKLatest)PC\lib\amd64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + true + + + Bin\XDKPC_2015\$(Platform)\$(Configuration)\ + Bin\XDKPC_2015\$(Platform)\$(Configuration)\ + DirectXTex + false + $(XboxOneXDKLatest)PC\include;$(DurangoXDK)PC\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(XboxOneXDKLatest)PC\lib\amd64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + true + + + Bin\XDKPC_2015\$(Platform)\$(Configuration)\ + Bin\XDKPC_2015\$(Platform)\$(Configuration)\ + DirectXTex + false + $(XboxOneXDKLatest)PC\include;$(DurangoXDK)PC\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(XboxOneXDKLatest)PC\lib\amd64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + true + + + + EnableAllWarnings + Disabled + MultiThreadedDebugDLL + true + true + Fast + Sync + %(AdditionalOptions) + _UNICODE;UNICODE;WIN32;_DEBUG;_LIB;_WIN7_PLATFORM_UPDATE;_WIN32_WINNT=0x0600;_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + EnableFastChecks + Use + DirectXTexP.h + $(IntDir)$(TargetName).pdb + + + %(AdditionalOptions) + %(AdditionalDependencies) + Windows + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + EnableAllWarnings + MaxSpeed + MultiThreadedDLL + true + true + true + Fast + Sync + %(AdditionalOptions) + _UNICODE;UNICODE;WIN32;NDEBUG;_LIB;_WIN7_PLATFORM_UPDATE;_WIN32_WINNT=0x0600;_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + Use + DirectXTexP.h + $(IntDir)$(TargetName).pdb + + + %(AdditionalOptions) + %(AdditionalDependencies) + true + Windows + true + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + EnableAllWarnings + MaxSpeed + MultiThreadedDLL + true + true + true + Fast + Sync + %(AdditionalOptions) + _UNICODE;UNICODE;WIN32;NDEBUG;PROFILE;_LIB;_WIN7_PLATFORM_UPDATE;_WIN32_WINNT=0x0600;_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + Use + DirectXTexP.h + $(IntDir)$(TargetName).pdb + + + %(AdditionalOptions) + %(AdditionalDependencies) + true + Windows + true + true + true + true + true + MachineX64 + AsInvoker + %(DelayLoadDLLs) + + + false + + + + + + + + + + + + + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + Document + + + Document + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTex/DirectXTex_XboxOneXDK_PC_2015.vcxproj.filters b/Kits/DirectXTex/DirectXTex_XboxOneXDK_PC_2015.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..2946e780f1638af7e30c51e208febfc6adb2b088 --- /dev/null +++ b/Kits/DirectXTex/DirectXTex_XboxOneXDK_PC_2015.vcxproj.filters @@ -0,0 +1,187 @@ + + + + + {68652706-b700-4472-9af7-a56a482bd896} + + + {9b7fcbc5-2533-4b88-b75b-d4803e55fa7c} + + + {eb989628-e889-44bf-837a-05c9f09b258e} + + + {a674c059-ed12-4d51-b5b3-44c34ce565da} + + + {d362e391-e683-4ba5-887a-042dae839583} + + + + + Header Files + + + Header Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Source Files\Shaders + + + Source Files\Shaders + + + Source Files\Shaders + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Compiled + + + Source Files\Shaders\Symbols + + + Source Files\Shaders\Symbols + + + Source Files\Shaders\Symbols + + + Source Files\Shaders\Symbols + + + Source Files\Shaders\Symbols + + + Source Files\Shaders\Symbols + + + Source Files\Shaders\Symbols + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTex/DirectXTexp.h b/Kits/DirectXTex/DirectXTexp.h new file mode 100644 index 0000000000000000000000000000000000000000..cb20422eeb1231371b9e6cdf07027426b38be9b7 --- /dev/null +++ b/Kits/DirectXTex/DirectXTexp.h @@ -0,0 +1,277 @@ +//------------------------------------------------------------------------------------- +// DirectXTexp.h +// +// DirectX Texture Library - Private header +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//------------------------------------------------------------------------------------- + +#pragma once + +// VS 2013 related Off by default warnings +#pragma warning(disable : 4619 4616 4350 4351 4472 4640) +// C4619/4616 #pragma warning warnings +// C4350 behavior change +// C4351 behavior change; warning removed in later versions +// C4472 'X' is a native enum: add an access specifier (private/public) to declare a WinRT enum +// C4640 construction of local static object is not thread-safe + +// Off by default warnings +#pragma warning(disable : 4061 4265 4365 4571 4623 4625 4626 4668 4710 4711 4746 4774 4820 4987 5026 5027 5031 5032) +// C4061 enumerator 'X' in switch of enum 'X' is not explicitly handled by a case label +// C4265 class has virtual functions, but destructor is not virtual +// C4365 signed/unsigned mismatch +// C4571 behavior change +// C4623 default constructor was implicitly defined as deleted +// C4625 copy constructor was implicitly defined as deleted +// C4626 assignment operator was implicitly defined as deleted +// C4668 not defined as a preprocessor macro +// C4710 function not inlined +// C4711 selected for automatic inline expansion +// C4746 volatile access of '' is subject to /volatile: setting +// C4774 format string expected in argument 3 is not a string literal +// C4820 padding added after data member +// C4987 nonstandard extension used +// C5026 move constructor was implicitly defined as deleted +// C5027 move assignment operator was implicitly defined as deleted +// C5031/5032 push/pop mismatches in windows headers + +// Windows 8.1 SDK related Off by default warnings +#pragma warning(disable : 4471 4917 4986 5029) +// C4471 forward declaration of an unscoped enumeration must have an underlying type +// C4917 a GUID can only be associated with a class, interface or namespace +// C4986 exception specification does not match previous declaration +// C5029 nonstandard extension used + +#pragma warning(push) +#pragma warning(disable : 4005) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NODRAWTEXT +#define NOGDI +#define NOBITMAP +#define NOMCX +#define NOSERVICE +#define NOHELP +#pragma warning(pop) + +#ifndef _WIN32_WINNT_WIN10 +#define _WIN32_WINNT_WIN10 0x0A00 +#endif + +#include + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#include +#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN10) +#include +#include +#else +#include +#endif + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include "directxtex.h" + +#include + +#include + +#include "scoped.h" + +#define TEX_FILTER_MASK 0xF00000 + +#define XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT DXGI_FORMAT(116) +#define XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT DXGI_FORMAT(117) +#define XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT DXGI_FORMAT(118) +#define XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS DXGI_FORMAT(119) +#define XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT DXGI_FORMAT(120) + +#define WIN10_DXGI_FORMAT_P208 DXGI_FORMAT(130) +#define WIN10_DXGI_FORMAT_V208 DXGI_FORMAT(131) +#define WIN10_DXGI_FORMAT_V408 DXGI_FORMAT(132) + +#ifndef XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM +#define XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM DXGI_FORMAT(189) +#endif + +#define XBOX_DXGI_FORMAT_R4G4_UNORM DXGI_FORMAT(190) + + +namespace DirectX +{ + //--------------------------------------------------------------------------------- + // WIC helper functions + DXGI_FORMAT __cdecl _WICToDXGI( _In_ const GUID& guid ); + bool __cdecl _DXGIToWIC( _In_ DXGI_FORMAT format, _Out_ GUID& guid, _In_ bool ignoreRGBvsBGR = false ); + + DWORD __cdecl _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID ); + + inline WICBitmapDitherType __cdecl _GetWICDither( _In_ DWORD flags ) + { + static_assert( TEX_FILTER_DITHER == 0x10000, "TEX_FILTER_DITHER* flag values don't match mask" ); + + static_assert(static_cast(TEX_FILTER_DITHER) == static_cast(WIC_FLAGS_DITHER), "TEX_FILTER_DITHER* should match WIC_FLAGS_DITHER*"); + static_assert(static_cast(TEX_FILTER_DITHER_DIFFUSION) == static_cast(WIC_FLAGS_DITHER_DIFFUSION), "TEX_FILTER_DITHER* should match WIC_FLAGS_DITHER*"); + + switch( flags & 0xF0000 ) + { + case TEX_FILTER_DITHER: + return WICBitmapDitherTypeOrdered4x4; + + case TEX_FILTER_DITHER_DIFFUSION: + return WICBitmapDitherTypeErrorDiffusion; + + default: + return WICBitmapDitherTypeNone; + } + } + + inline WICBitmapInterpolationMode __cdecl _GetWICInterp( _In_ DWORD flags ) + { + static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" ); + + static_assert(static_cast(TEX_FILTER_POINT) == static_cast(WIC_FLAGS_FILTER_POINT), "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*"); + static_assert(static_cast(TEX_FILTER_LINEAR) == static_cast(WIC_FLAGS_FILTER_LINEAR), "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*"); + static_assert(static_cast(TEX_FILTER_CUBIC) == static_cast(WIC_FLAGS_FILTER_CUBIC), "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*"); + static_assert(static_cast(TEX_FILTER_FANT) == static_cast(WIC_FLAGS_FILTER_FANT), "TEX_FILTER_* flags should match WIC_FLAGS_FILTER_*"); + + switch( flags & TEX_FILTER_MASK ) + { + case TEX_FILTER_POINT: + return WICBitmapInterpolationModeNearestNeighbor; + + case TEX_FILTER_LINEAR: + return WICBitmapInterpolationModeLinear; + + case TEX_FILTER_CUBIC: + return WICBitmapInterpolationModeCubic; + + case TEX_FILTER_FANT: + default: + return WICBitmapInterpolationModeFant; + } + } + + //--------------------------------------------------------------------------------- + // Image helper functions + void __cdecl _DetermineImageArray( _In_ const TexMetadata& metadata, _In_ DWORD cpFlags, + _Out_ size_t& nImages, _Out_ size_t& pixelSize ); + + _Success_(return != false) + bool __cdecl _SetupImageArray( _In_reads_bytes_(pixelSize) uint8_t *pMemory, _In_ size_t pixelSize, + _In_ const TexMetadata& metadata, _In_ DWORD cpFlags, + _Out_writes_(nImages) Image* images, _In_ size_t nImages ); + + //--------------------------------------------------------------------------------- + // Conversion helper functions + + enum TEXP_SCANLINE_FLAGS + { + TEXP_SCANLINE_NONE = 0, + TEXP_SCANLINE_SETALPHA = 0x1, // Set alpha channel to known opaque value + TEXP_SCANLINE_LEGACY = 0x2, // Enables specific legacy format conversion cases + }; + + enum CONVERT_FLAGS + { + CONVF_FLOAT = 0x1, + CONVF_UNORM = 0x2, + CONVF_UINT = 0x4, + CONVF_SNORM = 0x8, + CONVF_SINT = 0x10, + CONVF_DEPTH = 0x20, + CONVF_STENCIL = 0x40, + CONVF_SHAREDEXP = 0x80, + CONVF_BGR = 0x100, + CONVF_XR = 0x200, + CONVF_PACKED = 0x400, + CONVF_BC = 0x800, + CONVF_YUV = 0x1000, + CONVF_POS_ONLY = 0x2000, + CONVF_R = 0x10000, + CONVF_G = 0x20000, + CONVF_B = 0x40000, + CONVF_A = 0x80000, + CONVF_RGB_MASK = 0x70000, + CONVF_RGBA_MASK = 0xF0000, + }; + + DWORD __cdecl _GetConvertFlags( _In_ DXGI_FORMAT format ); + + void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize)) + _When_(pDestination != pSource, _Out_writes_bytes_(outSize)) + void* pDestination, _In_ size_t outSize, + _In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize, + _In_ DXGI_FORMAT format, _In_ DWORD flags ); + + void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_) + _When_(pDestination != pSource, _Out_writes_bytes_(outSize)) + void* pDestination, _In_ size_t outSize, + _In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize, + _In_ DXGI_FORMAT format, _In_ DWORD flags ); + + _Success_(return != false) + bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) void* pDestination, _In_ size_t outSize, + _In_ DXGI_FORMAT outFormat, + _In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize, + _In_ DXGI_FORMAT inFormat, _In_ DWORD flags ); + + _Success_(return != false) + bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count, + _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format ); + + _Success_(return != false) + bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count, + _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags ); + + _Success_(return != false) + bool __cdecl _StoreScanline( _Out_writes_bytes_(size) void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format, + _In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 ); + + _Success_(return != false) + bool __cdecl _StoreScanlineLinear( _Out_writes_bytes_(size) void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format, + _Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 ); + + _Success_(return != false) + bool __cdecl _StoreScanlineDither( _Out_writes_bytes_(size) void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format, + _Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z, + _Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors ); + + HRESULT __cdecl _ConvertToR32G32B32A32( _In_ const Image& srcImage, _Inout_ ScratchImage& image ); + + HRESULT __cdecl _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage ); + HRESULT __cdecl _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _Inout_ ScratchImage& image ); + HRESULT __cdecl _ConvertFromR32G32B32A32( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, + _In_ DXGI_FORMAT format, _Out_ ScratchImage& result ); + + void __cdecl _ConvertScanline( _Inout_updates_all_(count) XMVECTOR* pBuffer, _In_ size_t count, + _In_ DXGI_FORMAT outFormat, _In_ DXGI_FORMAT inFormat, _In_ DWORD flags ); + + //--------------------------------------------------------------------------------- + // DDS helper functions + HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags, + _Out_writes_bytes_to_opt_(maxsize, required) void* pDestination, _In_ size_t maxsize, _Out_ size_t& required ); + +}; // namespace diff --git a/Kits/DirectXTex/ReadMe.txt b/Kits/DirectXTex/ReadMe.txt new file mode 100644 index 0000000000000000000000000000000000000000..14696f5d73bd2c4562255bd702a387a08c8437f0 --- /dev/null +++ b/Kits/DirectXTex/ReadMe.txt @@ -0,0 +1,417 @@ +DIRECTX TEXTURE LIBRARY (DirectXTex) +------------------------------------ + +Copyright (c) Microsoft Corporation. All rights reserved. + +September 22, 2017 + +This package contains DirectXTex, a shared source library for reading and writing DDS +files, and performing various texture content processing operations including +resizing, format conversion, mip-map generation, block compression for Direct3D runtime +texture resources, and height-map to normal-map conversion. This library makes +use of the Windows Image Component (WIC) APIs. It also includes simple .TGA and .HDR +readers and writers since these image file formats are commonly used for texture content +processing pipelines, but are not currently supported by a built-in WIC codec. + +The source is written for Visual Studio 2013 or 2015. It is recommended that you +make use of VS 2013 Update 5 or VS 2015 Update 3 and Windows 7 Service Pack 1 or later. + +DirectXTex\ + This contains the DirectXTex library. This includes a full-featured DDS reader and writer + including legacy format conversions, a TGA reader and writer, a HDR reader and writer, + a WIC-based bitmap reader and writer (BMP, JPEG, PNG, TIFF, and HD Photo), and various + texture processing functions. This is intended primarily for tool usage. + + Note that the majority of the header files here are intended for internal implementation + of the library only (BC.h, BCDirectCompute.h, DDS.h, DirectXTexP.h, filters.h, and scoped.h). + Only DirectXTex.h is meant as a 'public' header for the library. + +Texconv\ + This DirectXTex sample is an implementation of the "texconv" command-line texture utility + from the DirectX SDK utilizing DirectXTex rather than D3DX. + + It supports the same arguments as the Texture Conversion Tool Extended (texconvex.exe) DirectX + SDK utility. The primary differences are the -10 and -11 arguments are not applicable and the + filter names (POINT, LINEAR, CUBIC, FANT or BOX, TRIANGLE, *_DITHER, *_DITHER_DIFFUSION). + This also includes support for the JPEG XR (HD Photo) bitmap format. + (see ) + + See for details. + +Texassemble\ + This DirectXTex sample is a command-line utility for creating cubemaps, volume maps, or + texture arrays from a set of individual input image files. + + See for details. + +Texdiag\ + This DirectXTex sample is a command-line utility for analyzing image contents, primarily for + debugging purposes. + + See + +DDSView\ + This DirectXTex sample is a simple Direct3D 11-based viewer for DDS files. For array textures + or volume maps, the "<" and ">" keyboard keys will show different images contained in the DDS. + The "1" through "0" keys can also be used to jump to a specific image index. + +DDSTextureLoader\ + This contains a streamlined version of the DirectX SDK sample DDSWithoutD3DX11 texture + loading code for a simple light-weight runtime DDS loader. This version only supports + Direct3D 11 or Direct3D 12 and performs no runtime pixel data conversions (i.e. 24bpp + legacy DDS files always fail). This is ideal for runtime usage, and supports the full + complement of Direct3D texture resources (1D, 2D, volume maps, cubemaps, mipmap levels, + texture arrays, BC formats, etc.). + +ScreenGrab\ + This contains screen grab modules for Direct3D 11 and Direct3D 12 primarily intended + for creating screenshots. The images are written as a DDS or as an image file format + using WIC. + +WICTextureLoader\ + This contains a Direct3D 11 and Direct3D 12 2D texture loader that uses WIC to load a + bitmap (BMP, JPEG, PNG, HD Photo, or other WIC supported file container), resize if needed + based on the current feature level (or by explicit parameter), format convert to a + DXGI_FORMAT if required, and then create a 2D texture. Note this does not support 1D textures, + volume textures, cubemaps, or texture arrays. DDSTextureLoader is recommended for fully + "precooked" textures for maximum performance and image quality, but this loader can be useful + for creating simple 2D texture from standard image files at runtime. + +NOTE: DDSTextureLoader, ScreenGrab, and WICTextureLoader are 'stand-alone' versions of the same + modules provided in the DirectX Tool Kit. + +All content and source code for this package are subject to the terms of the MIT License. +. + +Documentation is available at . + +For the latest version of DirectXTex, bug reports, etc. please visit the project site. + +http://go.microsoft.com/fwlink/?LinkId=248926 + +This project has adopted the Microsoft Open Source Code of Conduct. For more information see the +Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments. + +https://opensource.microsoft.com/codeofconduct/ + + +------------------------------------ +RELEASE NOTES + +* The alpha mode specification for DDS files was updated between the March 2013 and April 2013 releases. Any + DDS files created using the DDS_FLAGS_FORCE_DX10_EXT_MISC2 flag or the texconv -dx10 switch using the + March 2013 release should be refreshed. + +* Due to the underlying Windows BMP WIC codec, alpha channels are not supported for 16bpp or 32bpp BMP pixel format + files. The Windows 8.x and Windows 10 version of the Windows BMP WIC codec does support 32bpp pixel formats with + alpha when using the BITMAPV5HEADER file header. Note the updated WIC is available on Windows 7 SP1 with KB 2670838 + installed. + +* While DXGI 1.0 and DXGI 1.1 include 5:6:5 (DXGI_FORMAT_B5G6R5_UNORM) and 5:5:5:1 (DXGI_FORMAT_B5G5R5A1_UNORM) + pixel format enumerations, the DirectX 10.x and 11.0 Runtimes do not support these formats for use with Direct3D. + The DirectX 11.1 runtime, DXGI 1.2, and the WDDM 1.2 driver model fully support 16bpp formats (5:6:5, 5:5:5:1, and + 4:4:4:4). + +* WICTextureLoader cannot load .TGA or .HDR files unless the system has a 3rd party WIC codec installed. You + must use the DirectXTex library for TGA/HDR file format support without relying on an add-on WIC codec. + +* Loading of 96bpp floating-point TIFF files results in a corrupted image prior to Windows 8. This fix is available + on Windows 7 SP1 with KB 2670838 installed. + + +------------------------------------ +RELEASE HISTORY + +September 22, 2017 + Updated for VS 2017 15.3 update /permissive- changes + WIC writer and ScreenGrab updated to use non-sRGB metadata for PNG + texassemble, texconv, texdiag: added -flist option + +July 26, 2017 + Support for reading non-standard DDS files written by nVidia Texture Tools (NVTT) + Fix for ComputeMSE when using CMSE_IMAGE2_X2_BIAS + Fix for WIC writer then codec target format requires a palette + Code cleanup + +April 24, 2017 + VS 2017 project updates + Regenerated shaders using Windows 10 Creators Update SDK (15063) + Updated D3DX12 internal copy to latest version + +April 7, 2017 + VS 2017 updated for Windows Creators Update SDK (15063) + texassemble: -tonemap switch + texconv: -wicmulti switch + +January 31, 2017 + DirectX 12 versions of IsSupported, CreateTexture (PrepareUpload), and CaptureTexture + Update to DirectX 11 version of IsSupported + WIC format 40bppCMYKAlpha should be converted to RGBA8 rather than RGBA16 + DDS support for L8A8 with bitcount 8 rather than 16 + DXGI_FORMAT_R32G8X24_TYPELESS and DXGI_FORMAT_R24G8_TYPELESS should be IsDepthStencil formats + Updates to DDSTextureLoader, ScreenGrab, and WICTextureLoader + Minor code cleanup + +December 5, 2016 + Fixed over-validation in DDS header parsing + VS 2017 RC projects added + Minor code cleanup + +October 5, 2016 + *breaking change* + Renamed Evaluate to EvaluateImage, Transform to TransformImage + texdiag: new command-line tool for texture debugging + texconv: -bcmax, -bcquick, -tonemap, and -x2bias switches + texconv: overwrite writing and -y switch + texconv/texassemble: optional OpenEXR support + texassemble: command syntax with support for generating strip and cross images from cubemap + Updates to DDSTextureLoader, WICTextureLoader, and ScreenGrab + Minor code cleanup + +September 14, 2016 + HDR (RGBE Radiance) file format reader and writer + Evaluate and Transform functions for computing user-defined functions on images + Fix BC6H GPU shaders on WARP device + Fix for alignment issues on ARM devices in software compression codec + Added TEX_THRESHOLD_DEFAULT (0.5f) constant default alpha threshold value for Convert & Compress + Minor CaptureTexture optimization + texconv/texassemble: Support for .hdr file format + texconv: added -gpu switch to specify adapter to use for GPU-based compression codecs + texconv: added -badtails switch to enable loading of legacy DXTn DDS files with incomplete mipchain tails + texconv: added -c switch for old-school colorkey/chromakey transparency to alpha conversion + texconv: added -alpha switch for reverse premultiply along with TEX_PMALPHA_REVERSE flag + texconv: added wildcard support for input filename and optional -r switch for recursive search + +August 4, 2016 + CompileShader script updated to build external pdbs + Regenerated shaders using Windows 10 Anniversary Update SDK (14393) + +August 2, 2016 + Updated for VS 2015 Update 3 and Windows 10 SDK (14393) + +August 1, 2016 + Workaround for bug in XMStoreFloat3SE (impacts conversions to DXGI_FORMAT_R9G9B9E5_SHAREDEXP) + DDSTextureLoader12, WICTextureLoader12, and ScreenGrab12 for Direct3D 12 support + Minor code cleanup + +June 27, 2016 + texconv command-line tool -wicq and -wiclossless switches + Code cleanup + +April 26, 2016 + Optional callback from WIC reader functions to query additional metadata + Retired obsolete adapter code + Minor code cleanup + +February 23, 2016 + Fix to clean up partial or zero-length image files on failed write + Retired VS 2012 projects + +November 30, 2015 + texconv command-line tool -fl switch now supports 12.0 and 12.1 feature levels + Updated for VS 2015 Update 1 and Windows 10 SDK (10586) + +October 30, 2015 + DDS support for legacy bumpmap formats (V8U8, Q8W8V8U8, V16U16) + Fix for buffer overread in BC CPU compressor + Minor code cleanup + +August 18, 2015 + Added GetWICFactory and SetWICFactory + Updates for new DXGI 1.3 types + Xbox One platform updates + +July 29, 2015 + Fixed rounding problem with 32-bit RGBA/BGRA format conversions + texconv: use CPU parallel compression for BC1-BC5 (-singleproc disables) + Updated for VS 2015 and Windows 10 SDK RTM + Retired VS 2010 and Windows 8.0 Store projects + +June 18, 2015 + New BC_FLAGS_USE_3SUBSETS option for BC7 compressors; now defaults to skipping 3 subset blocks + Fixed bug with MakeTypeless and A8_UNORM + Fixed file length validation problem in LoadDDSFromFile + +March 27, 2015 + Added projects for Windows apps Technical Preview + Fixed bug with WIC-based mipmap generation for non-WIC supported formats + Fixed bug with WIC multiframe loader when resizing required + texconv: Added -nmap/-nmapamp for generating normal maps from height maps + texconv/texassemble: Updated to load multiframe WIC files (tiff, gif) + Minor code cleanup + +November 24, 2014 + Updates for Visual Studio 2015 Technical Preview + Minor code cleanup + +September 22, 2014 + Format conversion improvements and bug fixes (depth/stencil, alpha-only, float16, RGB -> 1 channel) + Fixed issue when BC decompressing non-standard compressed rowPitch images + Explicit calling-convention annotation for all 'public' functions + Code cleanup + Xbox One platform updates + +July 15, 2014 + texconv command-line tool fixes + Fixed problem with 'wide' images with CPU Compress + Updates to Xbox One platform support + +April 3, 2014 + Windows phone 8.1 platform support + +February 24, 2014 + Direct3D 11 video and Xbox One extended format support + New APIs: IsPlanar, IsPalettized, IsDepthStencil, ConvertToSinglePlane + Added 'alphaWeight' parameter to GPU Compress [breaking change] + texconv '-aw' switch to control the alpha weighting for the BC7 GPU compressor + Fixed bug with ordered dithering in non-WIC conversion codepaths + Fixed SaveToDDS* functions when using arbitrary row pitch values + +January 24, 2014 + Added sRGB flags for Compress (TEX_COMPRESS_SRGB*) + Added 'compress' flag parameter to GPU versions of Compress [breaking change] + Minor fix for potential rounding problem in GPU Compress + Code cleanup (removed DXGI_1_2_FORMATS control define; ScopedObject typedef removed) + Dropped VS 2010 support without the Windows 8.1 SDK (removed USE_XNAMATH control define) + +December 24, 2013 + texconv updated with -fl and -pow2 command-line switches + Fixed bug in Resize when doing custom filtering which occurred when exactly doubling the image size + Added move operators to ScratchImage and Blob classes + Xbox One platform support + +October 21, 2013 + Updated for Visual Studio 2013 and Windows 8.1 SDK RTM + PremultiplyAlpha updated with new 'flags' parameter and to use sRGB correct blending + Fixed colorspace conversion issue with DirectCompute compressor when compressing for BC7 SRGB + +August 13, 2013 + DirectCompute 4.0 BC6H/BC7 compressor integration + texconv utility uses DirectCompute compression by default for BC6H/BC7, -nogpu disables use of DirectCompute + +August 1, 2013 + Support for BC compression/decompression of non-power-of-2 mipmapped textures + Fixes for BC6H / BC7 codecs to better match published standard + Fix for BC4 / BC5 codecs when compressing RGB images + Minor fix for the BC1-3 codec + New optional flags for ComputeMSE to compare UNORM vs. SNORM images + New WIC loading flag added to control use of WIC metadata to return sRGB vs. non-sRGB formats + Code cleanup and /analyze fixes + Project file cleanup + Texconv utility uses parallel BC compression by default for BC6H/BC7, -singleproc disables multithreaded behavior + +July 1, 2013 + VS 2013 Preview projects added + SaveToWIC functions updated with new optional setCustomProps parameter + +June 15, 2013 + Custom filtering implementation for Resize & GenerateMipMaps(3D) - Point, Box, Linear, Cubic, and Triangle + TEX_FILTER_TRIANGLE finite low-pass triangle filter + TEX_FILTER_WRAP, TEX_FILTER_MIRROR texture semantics for custom filtering + TEX_FILTER_BOX alias for TEX_FILTER_FANT WIC + Ordered and error diffusion dithering for non-WIC conversion + sRGB gamma correct custom filtering and conversion + DDS_FLAGS_EXPAND_LUMINANCE - Reader conversion option for L8, L16, and A8L8 legacy DDS files + Added use of WIC metadata for sRGB pixel formats + Added BitsPerColor utility function + Fixed Convert threshold parameter usage + Non-power-of-2 volume map support, fixed bug with non-square volume maps + Texconv utility update with -xlum, -wrap, and -mirror options; reworked -if options for improved dithering + Texassemble utility for creating cubemaps, volume maps, and texture arrays + DDSTextureLoader and WICTextureLoader sync'd with DirectXTK versions + +April 16, 2013 + Updated alpha-mode metadata details in .DDS files + Added new control flags for Convert + Added new optional flags for ComputeMSE + Fixed conversion handling for sRGB formats + Fixed internal routines for handling R10G10B10_XR_BIAS_A2_UNORM, R9G9B9E5_SHAREDEXP, and FORMAT_R1_UNORM + Fixed WIC I/O for GUID_WICPixelFormat32bppRGBE pixel format files (HD Photo) + Fixed non-square image handling in GenerateMipMaps3D + Fixed some error handling in the DDS load code + +March 22, 2013 + Supports reading and writing alpha-mode (straight, premultiplied, etc.) metadata in .DDS files + Added build option to use WICCreateImagingFactory_Proxy instead of CoCreateInstance to obtain WIC factory + +January 29, 2013 + Added PremultiplyAlpha to DirectXTex; -pmalpha switch for texconv command-line tool + Fixed problem with forceSRGB implementation for Ex versions of CreateTexture, CreateShaderResourceView, DDSTextureLoader and WICTextureLoader + +December 11, 2012 + Ex versions of CreateTexture, CreateShaderResourceView, DDSTextureLoader and WICTextureLoader + Fixed BC2 and BC3 decompression issue for unusual color encoding case + Converted annotation to SAL2 for improved VS 2012 /analyze experience + Updated DirectXTex, DDSView, and Texconv with VS 2010 + Windows 8.0 SDK project using official 'property sheets' + +November 15, 2012 + Added support for WIC2 when available on Windows 8 and Windows 7 with KB 2670838 + Added optional targetGUID parameter to SaveWIC* APIs to influence final container pixel format choice + Fixed bug in SaveDDS* which was generating invalid DDS files for 1D dimension textures + Improved robustness of CaptureTexture when resolving MSAA source textures + Sync'd DDSTextureLoader, ScreenGrab, and WICTextureLoader standalone versions with latest DirectXTK release + +September 28, 2012 + Added ScreenGrab module for creating runtime screenshots + Renamed project files for better naming consistency + New Typeless utilities for DirectXTex + Some minor code cleanup for DirectXTex's WIC writer function + Bug fixes and new -tu/-tf options for texconv + +June 22, 2012 + Moved to using XNA Math 2.05 instead of XNA Math 2.04 for USE_XNAMATH builds + Fixed BGR vs. RGB color channel swizzle problem with 24bpp legacy .DDS files in DirectXTex + Update to DirectXTex WIC and WICTextureLoader for additional 96bpp float format handling on Windows 8 + +May 31, 2012 + Minor fix for DDSTextureLoader's retry fallback that can happen with 10level9 feature levels + Switched to use "_DEBUG" instead of "DEBUG" and cleaned up debug warnings + added Windows Store style application project files for DirectXTex + +April 20, 2012 + DirectTex's WIC-based writer opts-in for the Windows 8 BMP encoder option for writing 32 bpp RGBA files with the BITMAPV5HEADER + +March 30, 2012 + WICTextureLoader updated with Windows 8 WIC pixel formats + DirectXTex updated with limited non-power-of-2 texture support and TEX_FILTER_SEPARATE_ALPHA option + Texconv updated with '-sepalpha' command-line option + Added USE_XNAMATH control define to build DirectXTex using either XNAMath or DirectXMath + Added VS 2012 project files (which use DirectXMath instead of XNAMath and define DXGI_1_2_FORMATS) + +March 15, 2012 + Fix for resource leak in CreateShaderResourceView() Direct3D 11 helper function in DirectXTex + +March 5, 2012 + Fix for too much temp memory allocated by WICTextureLoader; cleaned up legacy 'min/max' macro usage in DirectXTex + +February 21, 2012 + WICTextureLoader updated to handle systems and device drivers without BGRA or 16bpp format support + +February 20, 2012 + Some code cleanup for DirectXTex and DDSTextureLoader + Fixed bug in 10:10:10:2 format fixup in the LoadDDSFromMemory function + Fixed bugs in "non-zero alpha" special-case handling in LoadTGAFromFile + Fixed bug in _SwizzleScanline when copying alpha channel for BGRA<->RGBA swizzling + +February 11, 2012 + Update of DDSTextureLoader to also build in Windows Store style apps; added WICTextureLoader + Added CMYK WIC pixel formats to the DirectXTex conversion table + +January 30, 2012 + Minor code-cleanup for DirectXTex to enable use of PCH through 'directxtexp.h' header + +January 24, 2011 + Some code-cleanup for DirectXTex + Added DXGI 1.2 implementation for DDSTextureLoader and DirectXTex guarded with DXGI_1_2_FORMATS compiliation define + +December 16, 2011 + Fixed x64 compilation warnings in DDSTextureLoader + +November 30, 2011 + Fixed some of the constants used in IsSupportedTexture(), + added ability to strip off top levels of mips in DDSTextureLoader, + changed DirectXTex to use CoCreateInstance rather than LoadLibrary to obtain the WIC factory, + a few minor /analyze related annotations for DirectXTex + +October 27, 2011 + Original release \ No newline at end of file diff --git a/Kits/DirectXTex/Shaders/BC6HEncode.hlsl b/Kits/DirectXTex/Shaders/BC6HEncode.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..227796e32681b91e09105a4f843609e2c1d38e65 --- /dev/null +++ b/Kits/DirectXTex/Shaders/BC6HEncode.hlsl @@ -0,0 +1,2566 @@ +//-------------------------------------------------------------------------------------- +// File: BC6HEncode.hlsl +// +// The Compute Shader for BC6H Encoder +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#define REF_DEVICE + +#define UINTLENGTH 32 +#define NCHANNELS 3 +#define SIGNED_F16 96 +#define UNSIGNED_F16 95 +#define MAX_FLOAT asfloat(0x7F7FFFFF) +#define MIN_FLOAT asfloat(0xFF7FFFFF) +#define MAX_INT asint(0x7FFFFFFF) +#define MIN_INT asint(0x80000000) + +cbuffer cbCS : register( b0 ) +{ + uint g_tex_width; + uint g_num_block_x; + uint g_format; //either SIGNED_F16 for DXGI_FORMAT_BC6H_SF16 or UNSIGNED_F16 for DXGI_FORMAT_BC6H_UF16 + uint g_mode_id; + uint g_start_block_id; + uint g_num_total_blocks; +}; + +static const uint candidateModeMemory[14] = { 0x00, 0x01, 0x02, 0x06, 0x0A, 0x0E, 0x12, 0x16, 0x1A, 0x1E, 0x03, 0x07, 0x0B, 0x0F }; +static const uint candidateModeFlag[14] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; +static const bool candidateModeTransformed[14] = { true, true, true, true, true, true, true, true, true, false, false, true, true, true }; +static const uint4 candidateModePrec[14] = { uint4(10,5,5,5), uint4(7,6,6,6), + uint4(11,5,4,4), uint4(11,4,5,4), uint4(11,4,4,5), uint4(9,5,5,5), + uint4(8,6,5,5), uint4(8,5,6,5), uint4(8,5,5,6), uint4(6,6,6,6), + uint4(10,10,10,10), uint4(11,9,9,9), uint4(12,8,8,8), uint4(16,4,4,4) }; + +/*static const uint4x4 candidateSection[32] = +{ + {0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1}, {0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1}, {0,1,1,1, 0,1,1,1, 0,1,1,1, 0,1,1,1}, {0,0,0,1, 0,0,1,1, 0,0,1,1, 0,1,1,1}, + {0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,1,1}, {0,0,1,1, 0,1,1,1, 0,1,1,1, 1,1,1,1}, {0,0,0,1, 0,0,1,1, 0,1,1,1, 1,1,1,1}, {0,0,0,0, 0,0,0,1, 0,0,1,1, 0,1,1,1}, + {0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,1,1}, {0,0,1,1, 0,1,1,1, 1,1,1,1, 1,1,1,1}, {0,0,0,0, 0,0,0,1, 0,1,1,1, 1,1,1,1}, {0,0,0,0, 0,0,0,0, 0,0,0,1, 0,1,1,1}, + {0,0,0,1, 0,1,1,1, 1,1,1,1, 1,1,1,1}, {0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1}, {0,0,0,0, 1,1,1,1, 1,1,1,1, 1,1,1,1}, {0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,1,1}, + {0,0,0,0, 1,0,0,0, 1,1,1,0, 1,1,1,1}, {0,1,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0}, {0,0,0,0, 0,0,0,0, 1,0,0,0, 1,1,1,0}, {0,1,1,1, 0,0,1,1, 0,0,0,1, 0,0,0,0}, + {0,0,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0}, {0,0,0,0, 1,0,0,0, 1,1,0,0, 1,1,1,0}, {0,0,0,0, 0,0,0,0, 1,0,0,0, 1,1,0,0}, {0,1,1,1, 0,0,1,1, 0,0,1,1, 0,0,0,1}, + {0,0,1,1, 0,0,0,1, 0,0,0,1, 0,0,0,0}, {0,0,0,0, 1,0,0,0, 1,0,0,0, 1,1,0,0}, {0,1,1,0, 0,1,1,0, 0,1,1,0, 0,1,1,0}, {0,0,1,1, 0,1,1,0, 0,1,1,0, 1,1,0,0}, + {0,0,0,1, 0,1,1,1, 1,1,1,0, 1,0,0,0}, {0,0,0,0, 1,1,1,1, 1,1,1,1, 0,0,0,0}, {0,1,1,1, 0,0,0,1, 1,0,0,0, 1,1,1,0}, {0,0,1,1, 1,0,0,1, 1,0,0,1, 1,1,0,0} +};*/ + +static const uint candidateSectionBit[32] = +{ + 0xCCCC, 0x8888, 0xEEEE, 0xECC8, + 0xC880, 0xFEEC, 0xFEC8, 0xEC80, + 0xC800, 0xFFEC, 0xFE80, 0xE800, + 0xFFE8, 0xFF00, 0xFFF0, 0xF000, + 0xF710, 0x008E, 0x7100, 0x08CE, + 0x008C, 0x7310, 0x3100, 0x8CCE, + 0x088C, 0x3110, 0x6666, 0x366C, + 0x17E8, 0x0FF0, 0x718E, 0x399C +}; + +static const uint candidateFixUpIndex1D[32] = +{ + 15,15,15,15, + 15,15,15,15, + 15,15,15,15, + 15,15,15,15, + 15, 2, 8, 2, + 2, 8, 8,15, + 2, 8, 2, 2, + 8, 8, 2, 2 +}; + +//0, 9, 18, 27, 37, 46, 55, 64 +static const uint aStep1[64] = {0,0,0,0,0,1,1,1, + 1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,3, + 3,3,3,3,3,3,3,3, + 3,4,4,4,4,4,4,4, + 4,4,5,5,5,5,5,5, + 5,5,5,6,6,6,6,6, + 6,6,6,6,7,7,7,7}; + +//0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 +static const uint aStep2[64] = { 0, 0, 0, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, + 9,10,10,10,10,10,11,11, + 11,11,12,12,12,12,13,13, + 13,13,14,14,14,14,15,15}; + +static const float3 RGB2LUM = float3(0.2126f, 0.7152f, 0.0722f); + +#define THREAD_GROUP_SIZE 64 +#define BLOCK_SIZE_Y 4 +#define BLOCK_SIZE_X 4 +#define BLOCK_SIZE (BLOCK_SIZE_Y * BLOCK_SIZE_X) + + +//Forward declaration +uint3 float2half( float3 pixel_f ); +int3 start_quantize( uint3 pixel_h ); +void quantize( inout int2x3 endPoint, uint prec ); +void finish_quantize_0( inout int bBadQuantize, inout int2x3 endPoint, uint4 prec, bool transformed ); +void finish_quantize_1( inout int bBadQuantize, inout int2x3 endPoint, uint4 prec, bool transformed ); +void finish_quantize( out bool bBadQuantize, inout int2x3 endPoint, uint4 prec, bool transformed ); + +void start_unquantize( inout int2x3 endPoint[2], uint4 prec, bool transformed ); +void start_unquantize( inout int2x3 endPoint, uint4 prec, bool transformed ); +void unquantize( inout int2x3 color, uint prec ); +uint3 finish_unquantize( int3 color ); +void generate_palette_unquantized8( out uint3 palette, int3 low, int3 high, int i ); +void generate_palette_unquantized16( out uint3 palette, int3 low, int3 high, int i ); +float3 half2float(uint3 color_h ); + +void block_package( inout uint4 block, int2x3 endPoint[2], uint mode_type, uint partition_index ); +void block_package( inout uint4 block, int2x3 endPoint, uint mode_type ); + +void swap(inout int3 lhs, inout int3 rhs) +{ + int3 tmp = lhs; + lhs = rhs; + rhs = tmp; +} + +Texture2D g_Input : register( t0 ); +StructuredBuffer g_InBuff : register( t1 ); + +RWStructuredBuffer g_OutBuff : register( u0 ); + +struct SharedData +{ + float3 pixel; + int3 pixel_ph; + float3 pixel_hr; + float pixel_lum; + float error; + uint best_mode; + uint best_partition; + int3 endPoint_low; + int3 endPoint_high; + float endPoint_lum_low; + float endPoint_lum_high; +}; + +groupshared SharedData shared_temp[THREAD_GROUP_SIZE]; + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void TryModeG10CS( uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID ) +{ + const uint MAX_USED_THREAD = 16; + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; + uint blockInGroup = GI / MAX_USED_THREAD; + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; + uint threadBase = blockInGroup * MAX_USED_THREAD; + uint threadInBlock = GI - threadBase; + +#ifndef REF_DEVICE + if (blockID >= g_num_total_blocks) + { + return; + } +#endif + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + if (threadInBlock < 16) + { + shared_temp[GI].pixel = g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ).rgb; + uint3 pixel_h = float2half( shared_temp[GI].pixel ); + shared_temp[GI].pixel_hr = half2float(pixel_h); + shared_temp[GI].pixel_lum = dot(shared_temp[GI].pixel_hr, RGB2LUM); + shared_temp[GI].pixel_ph = start_quantize( pixel_h ); + + shared_temp[GI].endPoint_low = shared_temp[GI].pixel_ph; + shared_temp[GI].endPoint_high = shared_temp[GI].pixel_ph; + shared_temp[GI].endPoint_lum_low = shared_temp[GI].pixel_lum; + shared_temp[GI].endPoint_lum_high = shared_temp[GI].pixel_lum; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 8) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 8].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 8].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 8].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 8].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 8].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 8].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 4].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 4].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 4].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 4].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 4].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 4].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 2].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 2].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 2].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 2].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 2].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 2].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 1].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 1].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 1].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 1].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 1].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 1].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + //ergod mode_type 11:14 + if ( threadInBlock == 0 ) + { + int2x3 endPoint; + // find_axis + endPoint[0] = shared_temp[threadBase + 0].endPoint_low; + endPoint[1] = shared_temp[threadBase + 0].endPoint_high; + + //compute_index + float3 span = endPoint[1] - endPoint[0];// fixed a bug in v0.2 + float span_norm_sqr = dot( span, span );// fixed a bug in v0.2 + float dotProduct = dot( span, shared_temp[threadBase + 0].pixel_ph - endPoint[0] );// fixed a bug in v0.2 + if ( span_norm_sqr > 0 && dotProduct >= 0 && uint( dotProduct * 63.49999 / span_norm_sqr ) > 32 ) + { + swap(endPoint[0], endPoint[1]); + + shared_temp[GI].endPoint_low = endPoint[0]; + shared_temp[GI].endPoint_high = endPoint[1]; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 4) + { + int2x3 endPoint; + endPoint[0] = shared_temp[threadBase + 0].endPoint_low; + endPoint[1] = shared_temp[threadBase + 0].endPoint_high; + + float3 span = endPoint[1] - endPoint[0]; + float span_norm_sqr = dot( span, span ); + + uint4 prec = candidateModePrec[threadInBlock + 10]; + int2x3 endPoint_q = endPoint; + quantize( endPoint_q, prec.x ); + + bool transformed = candidateModeTransformed[threadInBlock + 10]; + if (transformed) + { + endPoint_q[1] -= endPoint_q[0]; + } + + bool bBadQuantize; + finish_quantize( bBadQuantize, endPoint_q, prec, transformed ); + + start_unquantize( endPoint_q, prec, transformed ); + + unquantize( endPoint_q, prec.x ); + + float error = 0; + [loop]for ( uint j = 0; j < 16; j ++ ) + { + float dotProduct = dot( span, shared_temp[threadBase + j].pixel_ph - endPoint[0] );// fixed a bug in v0.2 + uint index = ( span_norm_sqr <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr ) ? aStep2[ uint( dotProduct * 63.49999 / span_norm_sqr ) ] : aStep2[63] ); + + uint3 pixel_rh; + generate_palette_unquantized16( pixel_rh, endPoint_q[0], endPoint_q[1], index ); + float3 pixel_r = half2float( pixel_rh ); + pixel_r -= shared_temp[threadBase + j].pixel_hr; + error += dot(pixel_r, pixel_r); + } + if ( bBadQuantize ) + error = 1e20f; + + shared_temp[GI].error = error; + shared_temp[GI].best_mode = candidateModeFlag[threadInBlock + 10]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 2) + { + if ( shared_temp[GI].error > shared_temp[GI + 2].error ) + { + shared_temp[GI].error = shared_temp[GI + 2].error; + shared_temp[GI].best_mode = shared_temp[GI + 2].best_mode; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + if ( shared_temp[GI].error > shared_temp[GI + 1].error ) + { + shared_temp[GI].error = shared_temp[GI + 1].error; + shared_temp[GI].best_mode = shared_temp[GI + 1].best_mode; + } + + g_OutBuff[blockID] = uint4(asuint(shared_temp[GI].error), shared_temp[GI].best_mode, 0, 0); + } +} + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void TryModeLE10CS( uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID ) +{ + const uint MAX_USED_THREAD = 32; + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; + uint blockInGroup = GI / MAX_USED_THREAD; + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; + uint threadBase = blockInGroup * MAX_USED_THREAD; + uint threadInBlock = GI - threadBase; + +#ifndef REF_DEVICE + if (blockID >= g_num_total_blocks) + { + return; + } + + if (asfloat(g_InBuff[blockID].x) < 1e-6f) + { + g_OutBuff[blockID] = g_InBuff[blockID]; + return; + } +#endif + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + if (threadInBlock < 16) + { + shared_temp[GI].pixel = g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ).rgb; + uint3 pixel_h = float2half( shared_temp[GI].pixel ); + shared_temp[GI].pixel_hr = half2float(pixel_h); + shared_temp[GI].pixel_lum = dot(shared_temp[GI].pixel_hr, RGB2LUM); + shared_temp[GI].pixel_ph = start_quantize( pixel_h ); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + //ergod mode_type 1:10 + if (threadInBlock < 32) + { + // find_axis + int2x3 endPoint[2]; + endPoint[0][0] = MAX_INT; + endPoint[0][1] = MIN_INT; + endPoint[1][0] = MAX_INT; + endPoint[1][1] = MIN_INT; + + float2 endPoint_lum[2]; + endPoint_lum[0][0] = MAX_FLOAT; + endPoint_lum[0][1] = MIN_FLOAT; + endPoint_lum[1][0] = MAX_FLOAT; + endPoint_lum[1][1] = MIN_FLOAT; + + uint bit = candidateSectionBit[threadInBlock]; + for ( uint i = 0; i < 16; i ++ ) + { + int3 pixel_ph = shared_temp[threadBase + i].pixel_ph; + float pixel_lum = shared_temp[threadBase + i].pixel_lum; + if ( (bit >> i) & 1 ) //It gets error when using "candidateSection" as "endPoint_ph" index + { + if (endPoint_lum[1][0] > pixel_lum) + { + endPoint[1][0] = pixel_ph; + endPoint_lum[1][0] = pixel_lum; + } + if (endPoint_lum[1][1] < pixel_lum) + { + endPoint[1][1] = pixel_ph; + endPoint_lum[1][1] = pixel_lum; + } + } + else + { + if (endPoint_lum[0][0] > pixel_lum) + { + endPoint[0][0] = pixel_ph; + endPoint_lum[0][0] = pixel_lum; + } + if (endPoint_lum[0][1] < pixel_lum) + { + endPoint[0][1] = pixel_ph; + endPoint_lum[0][1] = pixel_lum; + } + } + } + + //compute_index + float3 span[2];// fixed a bug in v0.2 + float span_norm_sqr[2];// fixed a bug in v0.2 + [unroll] + for (uint p = 0; p < 2; ++ p) + { + span[p] = endPoint[p][1] - endPoint[p][0]; + span_norm_sqr[p] = dot( span[p], span[p] ); + + float dotProduct = dot( span[p], shared_temp[threadBase + (0 == p ? 0 : candidateFixUpIndex1D[threadInBlock])].pixel_ph - endPoint[p][0] );// fixed a bug in v0.2 + if ( span_norm_sqr[p] > 0 && dotProduct >= 0 && uint( dotProduct * 63.49999 / span_norm_sqr[p] ) > 32 ) + { + span[p] = -span[p]; + swap(endPoint[p][0], endPoint[p][1]); + } + } + + uint4 prec = candidateModePrec[g_mode_id]; + int2x3 endPoint_q[2] = endPoint; + quantize( endPoint_q[0], prec.x ); + quantize( endPoint_q[1], prec.x ); + + bool transformed = candidateModeTransformed[g_mode_id]; + if (transformed) + { + endPoint_q[0][1] -= endPoint_q[0][0]; + endPoint_q[1][0] -= endPoint_q[0][0]; + endPoint_q[1][1] -= endPoint_q[0][0]; + } + + int bBadQuantize = 0; + finish_quantize_0( bBadQuantize, endPoint_q[0], prec, transformed ); + finish_quantize_1( bBadQuantize, endPoint_q[1], prec, transformed ); + + start_unquantize( endPoint_q, prec, transformed ); + + unquantize( endPoint_q[0], prec.x ); + unquantize( endPoint_q[1], prec.x ); + + float error = 0; + for ( uint j = 0; j < 16; j ++ ) + { + uint3 pixel_rh; + if ((bit >> j) & 1) + { + float dotProduct = dot( span[1], shared_temp[threadBase + j].pixel_ph - endPoint[1][0] );// fixed a bug in v0.2 + uint index = ( span_norm_sqr[1] <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr[1] ) ? aStep1[ uint( dotProduct * 63.49999 / span_norm_sqr[1] ) ] : aStep1[63] ); + generate_palette_unquantized8( pixel_rh, endPoint_q[1][0], endPoint_q[1][1], index ); + } + else + { + float dotProduct = dot( span[0], shared_temp[threadBase + j].pixel_ph - endPoint[0][0] );// fixed a bug in v0.2 + uint index = ( span_norm_sqr[0] <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr[0] ) ? aStep1[ uint( dotProduct * 63.49999 / span_norm_sqr[0] ) ] : aStep1[63] ); + generate_palette_unquantized8( pixel_rh, endPoint_q[0][0], endPoint_q[0][1], index ); + } + + float3 pixel_r = half2float( pixel_rh ); + pixel_r -= shared_temp[threadBase + j].pixel_hr; + error += dot(pixel_r, pixel_r); + } + if ( bBadQuantize ) + error = 1e20f; + + shared_temp[GI].error = error; + shared_temp[GI].best_mode = candidateModeFlag[g_mode_id]; + shared_temp[GI].best_partition = threadInBlock; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 16) + { + if ( shared_temp[GI].error > shared_temp[GI + 16].error ) + { + shared_temp[GI].error = shared_temp[GI + 16].error; + shared_temp[GI].best_mode = shared_temp[GI + 16].best_mode; + shared_temp[GI].best_partition = shared_temp[GI + 16].best_partition; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 8) + { + if ( shared_temp[GI].error > shared_temp[GI + 8].error ) + { + shared_temp[GI].error = shared_temp[GI + 8].error; + shared_temp[GI].best_mode = shared_temp[GI + 8].best_mode; + shared_temp[GI].best_partition = shared_temp[GI + 8].best_partition; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + if ( shared_temp[GI].error > shared_temp[GI + 4].error ) + { + shared_temp[GI].error = shared_temp[GI + 4].error; + shared_temp[GI].best_mode = shared_temp[GI + 4].best_mode; + shared_temp[GI].best_partition = shared_temp[GI + 4].best_partition; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + if ( shared_temp[GI].error > shared_temp[GI + 2].error ) + { + shared_temp[GI].error = shared_temp[GI + 2].error; + shared_temp[GI].best_mode = shared_temp[GI + 2].best_mode; + shared_temp[GI].best_partition = shared_temp[GI + 2].best_partition; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + if ( shared_temp[GI].error > shared_temp[GI + 1].error ) + { + shared_temp[GI].error = shared_temp[GI + 1].error; + shared_temp[GI].best_mode = shared_temp[GI + 1].best_mode; + shared_temp[GI].best_partition = shared_temp[GI + 1].best_partition; + } + + if (asfloat(g_InBuff[blockID].x) > shared_temp[GI].error) + { + g_OutBuff[blockID] = uint4(asuint(shared_temp[GI].error), shared_temp[GI].best_mode, shared_temp[GI].best_partition, 0); + } + else + { + g_OutBuff[blockID] = g_InBuff[blockID]; + } + } +} + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void EncodeBlockCS(uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID) +{ + const uint MAX_USED_THREAD = 32; + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; + uint blockInGroup = GI / MAX_USED_THREAD; + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; + uint threadBase = blockInGroup * MAX_USED_THREAD; + uint threadInBlock = GI - threadBase; + +#ifndef REF_DEVICE + if (blockID >= g_num_total_blocks) + { + return; + } +#endif + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + if (threadInBlock < 16) + { + shared_temp[GI].pixel = g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ).rgb; + shared_temp[GI].pixel_lum = dot(shared_temp[GI].pixel, RGB2LUM); + uint3 pixel_h = float2half( shared_temp[GI].pixel ); + shared_temp[GI].pixel_ph = start_quantize( pixel_h ); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + uint best_mode = g_InBuff[blockID].y; + uint best_partition = g_InBuff[blockID].z; + + uint4 block = 0; + + if (threadInBlock < 32) + { + int2x3 endPoint; + endPoint[0] = MAX_INT; + endPoint[1] = MIN_INT; + + float2 endPoint_lum; + endPoint_lum[0] = MAX_FLOAT; + endPoint_lum[1] = MIN_FLOAT; + + int2 endPoint_lum_index; + endPoint_lum_index[0] = -1; + endPoint_lum_index[1] = -1; + + int3 pixel_ph = shared_temp[threadBase + (threadInBlock & 0xF)].pixel_ph; + float pixel_lum = shared_temp[threadBase + (threadInBlock & 0xF)].pixel_lum; + if (threadInBlock < 16) + { + if (best_mode > 10) + { + endPoint[0] = endPoint[1] = pixel_ph; + endPoint_lum[0] = endPoint_lum[1] = pixel_lum; + } + else + { + uint bits = candidateSectionBit[best_partition]; + if (0 == ((bits >> threadInBlock) & 1)) + { + endPoint[0] = endPoint[1] = pixel_ph; + endPoint_lum[0] = endPoint_lum[1] = pixel_lum; + } + } + } + else + { + if (best_mode <= 10) + { + uint bits = candidateSectionBit[best_partition]; + if (1 == ((bits >> (threadInBlock & 0xF)) & 1)) + { + endPoint[0] = endPoint[1] = pixel_ph; + endPoint_lum[0] = endPoint_lum[1] = pixel_lum; + } + } + } + + shared_temp[GI].endPoint_low = endPoint[0]; + shared_temp[GI].endPoint_high = endPoint[1]; + + shared_temp[GI].endPoint_lum_low = endPoint_lum[0]; + shared_temp[GI].endPoint_lum_high = endPoint_lum[1]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if ((threadInBlock & 0xF) < 8) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 8].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 8].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 8].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 8].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 8].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 8].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if ((threadInBlock & 0xF) < 4) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 4].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 4].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 4].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 4].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 4].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 4].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if ((threadInBlock & 0xF) < 2) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 2].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 2].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 2].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 2].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 2].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 2].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if ((threadInBlock & 0xF) < 1) + { + if (shared_temp[GI].endPoint_lum_low > shared_temp[GI + 1].endPoint_lum_low) + { + shared_temp[GI].endPoint_low = shared_temp[GI + 1].endPoint_low; + shared_temp[GI].endPoint_lum_low = shared_temp[GI + 1].endPoint_lum_low; + } + if (shared_temp[GI].endPoint_lum_high < shared_temp[GI + 1].endPoint_lum_high) + { + shared_temp[GI].endPoint_high = shared_temp[GI + 1].endPoint_high; + shared_temp[GI].endPoint_lum_high = shared_temp[GI + 1].endPoint_lum_high; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 2) + { + // find_axis + int2x3 endPoint; + endPoint[0] = shared_temp[threadBase + threadInBlock * 16].endPoint_low; + endPoint[1] = shared_temp[threadBase + threadInBlock * 16].endPoint_high; + + uint fixup = 0; + if ((1 == threadInBlock) && (best_mode <= 10)) + { + fixup = candidateFixUpIndex1D[best_partition]; + } + + float3 span = endPoint[1] - endPoint[0]; + float span_norm_sqr = dot( span, span ); + float dotProduct = dot( span, shared_temp[threadBase + fixup].pixel_ph - endPoint[0] ); + if ( span_norm_sqr > 0 && dotProduct >= 0 && uint( dotProduct * 63.49999 / span_norm_sqr ) > 32 ) + { + swap(endPoint[0], endPoint[1]); + } + + shared_temp[GI].endPoint_low = endPoint[0]; + shared_temp[GI].endPoint_high = endPoint[1]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 16) + { + uint bits; + if (best_mode > 10) + { + bits = 0; + } + else + { + bits = candidateSectionBit[best_partition]; + } + + float3 span; + float dotProduct; + if ((bits >> threadInBlock) & 1) + { + span = shared_temp[threadBase + 1].endPoint_high - shared_temp[threadBase + 1].endPoint_low; + dotProduct = dot( span, shared_temp[threadBase + threadInBlock].pixel_ph - shared_temp[threadBase + 1].endPoint_low ); + } + else + { + span = shared_temp[threadBase + 0].endPoint_high - shared_temp[threadBase + 0].endPoint_low; + dotProduct = dot( span, shared_temp[threadBase + threadInBlock].pixel_ph - shared_temp[threadBase + 0].endPoint_low ); + } + float span_norm_sqr = dot( span, span ); + + if (best_mode > 10) + { + uint index = ( span_norm_sqr <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr ) ? aStep2[ uint( dotProduct * 63.49999 / span_norm_sqr ) ] : aStep2[63] ); + if (threadInBlock == 0) + { + block.z |= index << 1; + } + else if (threadInBlock < 8) + { + block.z |= index << (threadInBlock * 4); + } + else + { + block.w |= index << ((threadInBlock - 8) * 4); + } + } + else + { + uint index = ( span_norm_sqr <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr ) ? aStep1[ uint( dotProduct * 63.49999 / span_norm_sqr ) ] : aStep1[63] ); + + uint fixup = candidateFixUpIndex1D[best_partition]; + int2 offset = int2((fixup != 2), (fixup == 15)); + + if (threadInBlock == 0) + { + block.z |= index << 18; + } + else if (threadInBlock < 3) + { + block.z |= index << (20 + (threadInBlock - 1) * 3); + } + else if (threadInBlock < 5) + { + block.z |= index << (25 + (threadInBlock - 3) * 3 + offset.x); + } + else if (threadInBlock == 5) + { + block.w |= index >> !offset.x; + if (!offset.x) + { + block.z |= index << 31; + } + } + else if (threadInBlock < 9) + { + block.w |= index << (2 + (threadInBlock - 6) * 3 + offset.x); + } + else + { + block.w |= index << (11 + (threadInBlock - 9) * 3 + offset.y); + } + } + + shared_temp[GI].pixel_hr.xy = asfloat(block.zw); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 8) + { + shared_temp[GI].pixel_hr.xy = asfloat(asuint(shared_temp[GI].pixel_hr.xy) | asuint(shared_temp[GI + 8].pixel_hr.xy)); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + shared_temp[GI].pixel_hr.xy = asfloat(asuint(shared_temp[GI].pixel_hr.xy) | asuint(shared_temp[GI + 4].pixel_hr.xy)); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + shared_temp[GI].pixel_hr.xy = asfloat(asuint(shared_temp[GI].pixel_hr.xy) | asuint(shared_temp[GI + 2].pixel_hr.xy)); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + shared_temp[GI].pixel_hr.xy = asfloat(asuint(shared_temp[GI].pixel_hr.xy) | asuint(shared_temp[GI + 1].pixel_hr.xy)); + + block.zw = asuint(shared_temp[GI].pixel_hr.xy); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + bool transformed = candidateModeTransformed[best_mode - 1]; + uint4 prec = candidateModePrec[best_mode - 1]; + if (threadInBlock == 2) + { + int2x3 endPoint_q; + endPoint_q[0] = shared_temp[threadBase + 0].endPoint_low; + endPoint_q[1] = shared_temp[threadBase + 0].endPoint_high; + + quantize( endPoint_q, prec.x ); + if (transformed) + { + endPoint_q[1] -= endPoint_q[0]; + } + + shared_temp[GI].endPoint_low = endPoint_q[0]; + shared_temp[GI].endPoint_high = endPoint_q[1]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock == 3) + { + int3 ep0 = shared_temp[threadBase + 2].endPoint_low; + int2x3 endPoint_q; + endPoint_q[0] = shared_temp[threadBase + 1].endPoint_low; + endPoint_q[1] = shared_temp[threadBase + 1].endPoint_high; + + if (best_mode <= 10) + { + quantize( endPoint_q, prec.x ); + if (transformed) + { + endPoint_q[0] -= ep0; + endPoint_q[1] -= ep0; + } + + shared_temp[GI].endPoint_low = endPoint_q[0]; + shared_temp[GI].endPoint_high = endPoint_q[1]; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 2) + { + int2x3 endPoint_q; + endPoint_q[0] = shared_temp[threadBase + threadInBlock + 2].endPoint_low; + endPoint_q[1] = shared_temp[threadBase + threadInBlock + 2].endPoint_high; + + int bBadQuantize = 0; + if (threadInBlock == 0) + { + if (best_mode > 10) + { + finish_quantize( bBadQuantize, endPoint_q, prec, transformed ); + } + else + { + finish_quantize_0( bBadQuantize, endPoint_q, prec, transformed ); + } + } + else // if (threadInBlock == 1) + { + if (best_mode <= 10) + { + finish_quantize_1( bBadQuantize, endPoint_q, prec, transformed ); + } + } + + shared_temp[GI].endPoint_low = endPoint_q[0]; + shared_temp[GI].endPoint_high = endPoint_q[1]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if ( threadInBlock == 0 ) + { + int2x3 endPoint_q[2]; + endPoint_q[0][0] = shared_temp[threadBase + 0].endPoint_low; + endPoint_q[0][1] = shared_temp[threadBase + 0].endPoint_high; + endPoint_q[1][0] = shared_temp[threadBase + 1].endPoint_low; + endPoint_q[1][1] = shared_temp[threadBase + 1].endPoint_high; + + if ( best_mode > 10 ) + { + block_package( block, endPoint_q[0], best_mode ); + } + else + { + block_package( block, endPoint_q, best_mode, best_partition ); + } + + g_OutBuff[blockID] = block; + } +} + +uint float2half1( float f ) +{ + uint Result; + + uint IValue = asuint(f); + uint Sign = (IValue & 0x80000000U) >> 16U; + IValue = IValue & 0x7FFFFFFFU; + + if (IValue > 0x47FFEFFFU) + { + // The number is too large to be represented as a half. Saturate to infinity. + Result = 0x7FFFU; + } + else + { + if (IValue < 0x38800000U) + { + // The number is too small to be represented as a normalized half. + // Convert it to a denormalized value. + uint Shift = 113U - (IValue >> 23U); + IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift; + } + else + { + // Rebias the exponent to represent the value as a normalized half. + IValue += 0xC8000000U; + } + + Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U)&0x7FFFU; + } + return (Result|Sign); +} + +uint3 float2half( float3 endPoint_f ) +{ + //uint3 sign = asuint(endPoint_f) & 0x80000000; + //uint3 expo = asuint(endPoint_f) & 0x7F800000; + //uint3 base = asuint(endPoint_f) & 0x007FFFFF; + //return ( expo < 0x33800000 ) ? 0 + // //0x33800000 indicating 2^-24, which is minimal denormalized number that half can present + // : ( ( expo < 0x38800000 ) ? ( sign >> 16 ) | ( ( base + 0x00800000 ) >> ( 23 - ( ( expo - 0x33800000 ) >> 23 ) ) )//fixed a bug in v0.2 + // //0x38800000 indicating 2^-14, which is minimal normalized number that half can present, so need to use denormalized half presentation + // : ( ( expo == 0x7F800000 || expo > 0x47000000 ) ? ( ( sign >> 16 ) | 0x7bff ) + // // treat NaN as INF, treat INF (including NaN) as the maximum/minimum number that half can present + // // 0x47000000 indicating 2^15, which is maximum exponent that half can present, so cut to 0x7bff which is the maximum half number + // : ( ( sign >> 16 ) | ( ( ( expo - 0x38000000 ) | base ) >> 13 ) ) ) ); + + + return uint3( float2half1( endPoint_f.x ), float2half1( endPoint_f.y ), float2half1( endPoint_f.z ) ); +} +int3 start_quantize( uint3 pixel_h ) +{ + if ( g_format == UNSIGNED_F16 ) + { + return asint( ( pixel_h << 6 ) / 31 ); + } + else + { + return ( pixel_h < 0x8000 ) ? ( ( pixel_h == 0x7bff ) ? 0x7fff : asint( ( pixel_h << 5 ) / 31 ) )// fixed a bug in v0.2 + : ( ( pixel_h == 0x7bff ) ? 0xffff8001 : -asint( ( ( 0x00007fff & pixel_h ) << 5 ) / 31 ) );// fixed a bug in v0.2 + } +} +void quantize( inout int2x3 endPoint, uint prec ) +{ + int iprec = asint( prec ); + if ( g_format == UNSIGNED_F16 ) + { + endPoint = ( ( iprec >= 15 ) | ( endPoint == 0 ) ) ? endPoint + : ( ( endPoint == asint(0xFFFF) ) ? ( ( 1 << iprec ) - 1 ) + : ( ( ( endPoint << iprec ) + asint(0x0000) ) >> 16 ) ); + } + else + { + endPoint = ( ( iprec >= 16 ) | ( endPoint == 0 ) ) ? endPoint + : ( ( endPoint >= 0 ) ? ( ( endPoint == asint(0x7FFF) ) ? ( ( 1 << ( iprec - 1 ) ) - 1 ) : ( ( ( endPoint << ( iprec - 1 ) ) + asint(0x0000) ) >> 15 ) ) + : ( ( -endPoint == asint(0x7FFF) ) ? -( ( 1 << ( iprec - 1 ) ) - 1 ) : -( ( ( -endPoint << ( iprec - 1 ) ) + asint(0x0000) ) >> 15 ) ) ); + } +} +void finish_quantize_0( inout int bBadQuantize, inout int2x3 endPoint, uint4 prec, bool transformed ) +{ + if ( transformed ) + { + bool3 bBadComponent = ( endPoint[1] >= 0 ) ? ( endPoint[1] >= ( 1 << ( prec.yzw - 1 ) ) ) + : ( -endPoint[1] > ( 1 << ( prec.yzw - 1 ) ) ); + bBadQuantize |= any(bBadComponent); + + endPoint[0] = endPoint[0] & ( ( 1 << prec.x ) - 1 ); + endPoint[1] = ( endPoint[1] >= 0 ) ? ( ( endPoint[1] >= ( 1 << ( prec.yzw - 1 ) ) ) ? ( ( 1 << ( prec.yzw - 1 ) ) - 1 ) : endPoint[1] ) + : ( ( -endPoint[1] > ( 1 << ( prec.yzw - 1 ) ) ) ? ( 1 << ( prec.yzw - 1 ) ) : ( endPoint[1] & ( ( 1 << prec.yzw ) - 1 ) ) ); + } + else + { + endPoint &= ( ( 1 << prec.x ) - 1 ); + } +} +void finish_quantize_1( inout int bBadQuantize, inout int2x3 endPoint, uint4 prec, bool transformed ) +{ + if ( transformed ) + { + bool2x3 bBadComponent; + bBadComponent[0] = ( endPoint[0] >= 0 ) ? ( endPoint[0] >= ( 1 << ( prec.yzw - 1 ) ) ) + : ( -endPoint[0] > ( 1 << ( prec.yzw - 1 ) ) ); + bBadComponent[1] = ( endPoint[1] >= 0 ) ? ( endPoint[1] >= ( 1 << ( prec.yzw - 1 ) ) ) + : ( -endPoint[1] > ( 1 << ( prec.yzw - 1 ) ) ); + bBadQuantize |= any(bBadComponent); + + endPoint[0] = ( endPoint[0] >= 0 ) ? ( ( endPoint[0] >= ( 1 << ( prec.yzw - 1 ) ) ) ? ( ( 1 << ( prec.yzw - 1 ) ) - 1 ) : endPoint[0] ) + : ( ( -endPoint[0] > ( 1 << ( prec.yzw - 1 ) ) ) ? ( 1 << ( prec.yzw - 1 ) ) : ( endPoint[0] & ( ( 1 << prec.yzw ) - 1 ) ) ); + endPoint[1] = ( endPoint[1] >= 0 ) ? ( ( endPoint[1] >= ( 1 << ( prec.yzw - 1 ) ) ) ? ( ( 1 << ( prec.yzw - 1 ) ) - 1 ) : endPoint[1] ) + : ( ( -endPoint[1] > ( 1 << ( prec.yzw - 1 ) ) ) ? ( 1 << ( prec.yzw - 1 ) ) : ( endPoint[1] & ( ( 1 << prec.yzw ) - 1 ) ) ); + } + else + { + endPoint &= ( ( 1 << prec.x ) - 1 ); + } +} +void finish_quantize( out bool bBadQuantize, inout int2x3 endPoint, uint4 prec, bool transformed ) +{ + if ( transformed ) + { + bool3 bBadComponent; + bBadComponent = ( endPoint[1] >= 0 ) ? ( endPoint[1] >= ( 1 << ( prec.yzw - 1 ) ) ) + : ( -endPoint[1] > ( 1 << ( prec.yzw - 1 ) ) ); + bBadQuantize = any( bBadComponent ); + + endPoint[0] = endPoint[0] & ( ( 1 << prec.x ) - 1 ); + endPoint[1] = ( endPoint[1] >= 0 ) ? ( ( endPoint[1] >= ( 1 << ( prec.yzw - 1 ) ) ) ? ( ( 1 << ( prec.yzw - 1 ) ) - 1 ) : endPoint[1] ) + : ( ( -endPoint[1] > ( 1 << ( prec.yzw - 1 ) ) ) ? ( 1 << ( prec.yzw - 1 ) ) : ( endPoint[1] & ( ( 1 << prec.yzw ) - 1 ) ) ); + } + else + { + endPoint &= ( ( 1 << prec.x ) - 1 ); + + bBadQuantize = 0; + } +} + +void SIGN_EXTEND( uint3 prec, inout int3 color ) +{ + uint3 p = 1 << (prec - 1); + color = (color & p) ? (color & (p - 1)) - p : color; +} + +void sign_extend( bool transformed, uint4 prec, inout int2x3 endPoint ) +{ + if ( g_format == SIGNED_F16 ) + SIGN_EXTEND( prec.x, endPoint[0] ); + if ( g_format == SIGNED_F16 || transformed ) + SIGN_EXTEND( prec.yzw, endPoint[1] ); +} + +void sign_extend( bool transformed, uint4 prec, inout int2x3 endPoint[2] ) +{ + if ( g_format == SIGNED_F16 ) + SIGN_EXTEND( prec.x, endPoint[0][0] ); + if ( g_format == SIGNED_F16 || transformed ) + { + SIGN_EXTEND( prec.yzw, endPoint[0][1] ); + SIGN_EXTEND( prec.yzw, endPoint[1][0] ); + SIGN_EXTEND( prec.yzw, endPoint[1][1] ); + } +} +void start_unquantize( inout int2x3 endPoint[2], uint4 prec, bool transformed ) +{ + sign_extend( transformed, prec, endPoint ); + if ( transformed ) + { + endPoint[0][1] += endPoint[0][0]; + endPoint[1][0] += endPoint[0][0]; + endPoint[1][1] += endPoint[0][0]; + } +} +void start_unquantize( inout int2x3 endPoint, uint4 prec, bool transformed ) +{ + sign_extend( transformed, prec, endPoint ); + if ( transformed ) + endPoint[1] += endPoint[0]; +} +void unquantize( inout int2x3 color, uint prec ) +{ + int iprec = asint( prec ); + if (g_format == UNSIGNED_F16 ) + { + if (prec < 15) + { + color = (color != 0) ? (color == ((1 << iprec) - 1) ? 0xFFFF : (((color << 16) + 0x8000) >> iprec)) : color; + } + } + else + { + if (prec < 16) + { + uint2x3 s = color >= 0 ? 0 : 1; + color = abs(color); + color = (color != 0) ? (color >= ((1 << (iprec - 1)) - 1) ? 0x7FFF : (((color << 15) + 0x4000) >> (iprec - 1))) : color; + color = s > 0 ? -color : color; + } + } +} +uint3 finish_unquantize( int3 color ) +{ + if ( g_format == UNSIGNED_F16 ) + color = ( color * 31 ) >> 6; + else + { + color = ( color < 0 ) ? -( ( -color * 31 ) >> 5 ) : ( color * 31 ) >> 5; + color = ( color < 0 ) ? ( ( -color ) | 0x8000 ) : color; + } + return asuint(color); +} +void generate_palette_unquantized8( out uint3 palette, int3 low, int3 high, int i ) +{ + static const int aWeight3[] = {0, 9, 18, 27, 37, 46, 55, 64}; + + int3 tmp = ( low * ( 64 - aWeight3[i] ) + high * aWeight3[i] + 32 ) >> 6; + palette = finish_unquantize( tmp ); +} +void generate_palette_unquantized16( out uint3 palette, int3 low, int3 high, int i ) +{ + static const int aWeight4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64}; + + int3 tmp = ( low * ( 64 - aWeight4[i] ) + high * aWeight4[i] + 32 ) >> 6; + palette = finish_unquantize( tmp ); +} + +float half2float1( uint Value ) +{ + uint Mantissa = (uint)(Value & 0x03FF); + + uint Exponent; + if ((Value & 0x7C00) != 0) // The value is normalized + { + Exponent = (uint)((Value >> 10) & 0x1F); + } + else if (Mantissa != 0) // The value is denormalized + { + // Normalize the value in the resulting float + Exponent = 1; + + do + { + Exponent--; + Mantissa <<= 1; + } while ((Mantissa & 0x0400) == 0); + + Mantissa &= 0x03FF; + } + else // The value is zero + { + Exponent = (uint)(-112); + } + + uint Result = ((Value & 0x8000) << 16) | // Sign + ((Exponent + 112) << 23) | // Exponent + (Mantissa << 13); // Mantissa + + return asfloat(Result); +} + +float3 half2float(uint3 color_h ) +{ + //uint3 sign = color_h & 0x8000; + //uint3 expo = color_h & 0x7C00; + //uint3 base = color_h & 0x03FF; + //return ( expo == 0 ) ? asfloat( ( sign << 16 ) | asuint( float3(base) / 16777216 ) ) //16777216 = 2^24 + // : asfloat( ( sign << 16 ) | ( ( ( expo + 0x1C000 ) | base ) << 13 ) ); //0x1C000 = 0x1FC00 - 0x3C00 + + return float3( half2float1( color_h.x ), half2float1( color_h.y ), half2float1( color_h.z ) ); +} + +void block_package( inout uint4 block, int2x3 endPoint[2], uint mode_type, uint partition_index ) // for mode 1 - 10 +{ + block.xy = 0; + block.z &= 0xFFFC0000; + + //block.z |= (partition_index & 0x1f) << 13; + + if ( mode_type == candidateModeFlag[0]) + { + /*block.x = candidateModeMemory[0]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00007FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x01FF8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.x |= ( endPoint[1][0].g >> 2 ) & 0x00000004; + block.x |= ( endPoint[1][0].b >> 1 ) & 0x00000008; + block.x |= endPoint[1][1].b & 0x00000010; + block.y |= ( ( endPoint[0][0].b >> 7 ) & 0x00000007 ); + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000000F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0003E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x0F800000 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000003E); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.y |= ( ( endPoint[1][1].g << 4 ) & 0x00000100 ); + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000F80); + block.yz |= ( ( endPoint[1][1].b << uint2(27, 9) ) & uint2(0x10000000, 0x00001000) ) | ( ( endPoint[1][1].b << uint2(18, 4) ) & uint2(0x00040000, 0x00000040) ); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[0] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[0] >> 1) & 1) << 1; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 2; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 3; + block.x |= ((endPoint[1][1].b >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0][0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0][0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0][0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0][0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0][0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0][0].b >> 9) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1][1].g >> 4) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1][1].b >> 0) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1][1].b >> 1) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[1]) + { + /*block.x = candidateModeMemory[1]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00000FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x003F8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000001F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0007E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x1F800000 ); + block.x |= ( ( endPoint[1][0].g >> 3 ) & 0x00000004 ) | ( ( endPoint[1][0].g << 20 ) & 0x01000000 ); + block.x |= ( endPoint[1][1].g >> 1 ) & 0x00000018; + block.x |= ( ( endPoint[1][1].b << 21 ) & 0x00800000 ) | ( ( endPoint[1][1].b << 12 ) & 0x00003000 ); + block.x |= ( ( endPoint[1][0].b << 17 ) & 0x00400000 ) | ( ( endPoint[1][0].b << 10 ) & 0x00004000 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000007E); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00001F80); + block.y |= ( ( endPoint[1][1].b >> 4 ) & 0x00000002 ) | ( ( endPoint[1][1].b >> 2 ) & 0x00000004 ) | ( ( endPoint[1][1].b >> 3 ) & 0x00000001 ); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[1] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[1] >> 1) & 1) << 1; + block.x |= ((endPoint[1][0].g >> 5) & 1) << 2; + block.x |= ((endPoint[1][1].g >> 4) & 1) << 3; + block.x |= ((endPoint[1][1].g >> 5) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[1][1].b >> 0) & 1) << 12; + block.x |= ((endPoint[1][1].b >> 1) & 1) << 13; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[1][0].b >> 5) & 1) << 22; + block.x |= ((endPoint[1][1].b >> 2) & 1) << 23; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[1][1].b >> 3) & 1) << 0; + block.y |= ((endPoint[1][1].b >> 5) & 1) << 1; + block.y |= ((endPoint[1][1].b >> 4) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[0][1].r >> 5) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[0][1].g >> 5) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[0][1].b >> 5) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][0].r >> 5) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].r >> 5) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[2]) + { + /*block.x = candidateModeMemory[2]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00007FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x01FF8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0][0].r >> 2 ) & 0x00000100; + block.y |= ( endPoint[0][0].g << 7 ) & 0x00020000; + block.y |= ( ( endPoint[0][0].b << 17 ) & 0x08000000 ) | ( ( endPoint[0][0].b >> 7 ) & 0x00000007 ); + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000000F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0001E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x07800000 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000003E); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000F80); + block.yz |= ( ( endPoint[1][1].b << uint2(27, 9) ) & uint2(0x10000000, 0x00001000) ) | ( ( endPoint[1][1].b << uint2(18, 4) ) & uint2(0x00040000, 0x00000040) ); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[2] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[2] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[2] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[2] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[2] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0][0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0][0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0][0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0][0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0][0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0][0].b >> 9) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[0][0].r >> 10) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][0].g >> 10) & 1) << 17; + block.y |= ((endPoint[1][1].b >> 0) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][0].b >> 10) & 1) << 27; + block.y |= ((endPoint[1][1].b >> 1) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[3]) + { + /*block.x = candidateModeMemory[3]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00007FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x01FF8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0][0].r >> 3 ) & 0x00000080; + block.y |= ( endPoint[0][0].g << 8 ) & 0x00040000; + block.y |= ( ( endPoint[0][0].b << 17 ) & 0x08000000 ) | ( ( endPoint[0][0].b >> 7 ) & 0x00000007 ); + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x00000078 ) | ( ( endPoint[0][1].g << 13 ) & 0x0003E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x07800000 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000001E); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.y |= ( ( endPoint[1][1].g << 4 ) & 0x00000100 ); + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000780); + block.yz |= ( endPoint[1][1].b << uint2(27, 9) ) & uint2(0x10000000, 0x00001000); + block.z |= ( ( endPoint[1][0].g << 7 ) & 0x00000800 ); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001; + block.z |= ( endPoint[1][1].b << 4 ) & 0x00000040; + block.z |= ( endPoint[1][1].b << 5 ) & 0x00000020;*/ + + block.x |= ((candidateModeMemory[3] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[3] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[3] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[3] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[3] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0][0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0][0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0][0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0][0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0][0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0][0].b >> 9) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][0].r >> 10) & 1) << 7; + block.y |= ((endPoint[1][1].g >> 4) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[0][0].g >> 10) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][0].b >> 10) & 1) << 27; + block.y |= ((endPoint[1][1].b >> 1) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][1].b >> 0) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][0].g >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[4]) + { + /*block.x = candidateModeMemory[4]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00007FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x01FF8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0][0].r >> 3 ) & 0x00000080; + block.y |= ( endPoint[0][0].g << 7 ) & 0x00020000; + block.y |= ( ( endPoint[0][0].b << 18 ) & 0x10000000 ) | ( ( endPoint[0][0].b >> 7 ) & 0x00000007 ); + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x00000078 ) | ( ( endPoint[0][1].g << 13 ) & 0x0001E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x0F800000 ); + block.y |= ( ( endPoint[1][0].g << 9 ) & 0x00001E00 ) | ( ( endPoint[1][0].b << 4 ) & 0x00000100 ); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000780); + block.yz |= ( endPoint[1][1].b << uint2(18, 4) ) & uint2(0x00040000, 0x00000060); + block.z |= ( endPoint[1][0].r << 1 ) & 0x0000001E; + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001; + block.z |= ( ( endPoint[1][1].b << 7 ) & 0x00000800 ) | ( ( endPoint[1][1].b << 9 ) & 0x00001000 );*/ + + block.x |= ((candidateModeMemory[4] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[4] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[4] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[4] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[4] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0][0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0][0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0][0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0][0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0][0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0][0].b >> 9) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][0].r >> 10) & 1) << 7; + block.y |= ((endPoint[1][0].b >> 4) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][0].g >> 10) & 1) << 17; + block.y |= ((endPoint[1][1].b >> 0) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[0][0].b >> 10) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][1].b >> 1) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].b >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[5]) + { + /*block.x = candidateModeMemory[5]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00003FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x00FF8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000); + block.y |= ( endPoint[0][0].b >> 7 ) & 0x00000003; + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000000F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0003E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x0F800000 ); + block.x |= ( ( endPoint[1][0].g << 20 ) & 0x01000000 ) | ( ( endPoint[1][0].b << 10 ) & 0x00004000 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000003E); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.y |= ( ( endPoint[1][1].g << 4 ) & 0x00000100 ) | ( ( endPoint[1][1].b >> 2 ) & 0x00000004 ); + block.y |= ( ( endPoint[1][1].b << 27 ) & 0x10000000 ); + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000F80); + block.yz |= ( endPoint[1][1].b << uint2(18, 4) ) & uint2(0x00040000, 0x00000040); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001; + block.z |= ( ( endPoint[1][1].b << 9 ) & 0x00001000 );*/ + + block.x |= ((candidateModeMemory[5] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[5] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[5] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[5] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[5] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0][0].r >> 8) & 1) << 13; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0][0].g >> 8) & 1) << 23; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0][0].b >> 8) & 1) << 1; + block.y |= ((endPoint[1][1].b >> 4) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1][1].g >> 4) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1][1].b >> 0) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1][1].b >> 1) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[6]) + { + /*block.x = candidateModeMemory[6]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00001FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x007F8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0][0].b >> 7 ) & 0x00000001; + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000001F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0003E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x0F800000 ); + block.x |= ( ( endPoint[1][0].g << 20 ) & 0x01000000 ) | ( ( endPoint[1][0].b << 10 ) & 0x00004000); + block.x |= ( ( endPoint[1][1].g << 9 ) & 0x00002000 ) | ( ( endPoint[1][1].b << 21 ) & 0x00800000); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000007E); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00001F80); + block.y |= ( ( endPoint[1][1].b >> 2 ) & 0x00000006 ); + block.y |= ( ( endPoint[1][1].b << 27 ) & 0x10000000 ) | ( ( endPoint[1][1].b << 18 ) & 0x00040000 ); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[6] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[6] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[6] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[6] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[6] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[1][1].g >> 4) & 1) << 13; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[1][1].b >> 2) & 1) << 23; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[1][1].b >> 3) & 1) << 1; + block.y |= ((endPoint[1][1].b >> 4) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[0][1].r >> 5) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1][1].b >> 0) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1][1].b >> 1) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][0].r >> 5) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].r >> 5) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[7]) + { + /*block.x = candidateModeMemory[7]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00001FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x007F8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0][0].b >> 7 ) & 0x00000001; + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000000F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0007E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x0F800000 ); + block.x |= ( ( endPoint[1][0].g << 20 ) & 0x01000000 ) | ( ( endPoint[1][0].b << 10 ) & 0x00004000 ); + block.x |= ( ( endPoint[1][0].g << 18 ) & 0x00800000 ); + block.x |= ( ( endPoint[1][1].b << 13 ) & 0x00002000 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000003E); + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000F80); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.y |= ( ( endPoint[1][1].g >> 4 ) & 0x00000002 ) | ( ( endPoint[1][1].g << 4 ) & 0x00000100 ) | ( ( endPoint[1][1].b >> 2 ) & 0x00000004 ); + block.y |= ( endPoint[1][1].b << 27 ) & 0x10000000; + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001; + block.z |= ( ( endPoint[1][1].b << 9 ) & 0x00001000 ) | ( ( endPoint[1][1].b << 4 ) & 0x00000040 );*/ + + block.x |= ((candidateModeMemory[7] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[7] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[7] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[7] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[7] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[1][1].b >> 0) & 1) << 13; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[1][0].g >> 5) & 1) << 23; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[1][1].g >> 5) & 1) << 1; + block.y |= ((endPoint[1][1].b >> 4) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1][1].g >> 4) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[0][1].g >> 5) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1][1].b >> 1) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[8]) + { + /*block.x = candidateModeMemory[8]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x00001FE0 ) | ( ( endPoint[0][0].g << 15 ) & 0x007F8000 ) | ( ( endPoint[0][0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0][0].b >> 7 ) & 0x00000001; + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000000F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0003E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x1F800000 ); + block.x |= ( ( endPoint[1][0].g << 20 ) & 0x01000000 ) | ( ( endPoint[1][0].b << 10 ) & 0x00004000 ); + block.x |= ( ( endPoint[1][0].b << 18 ) & 0x00800000 ); + block.x |= ( endPoint[1][1].b << 12 ) & 0x00002000; + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.y |= ( ( endPoint[1][1].g << 4 ) & 0x00000100 ) | ( ( endPoint[1][1].b >> 4 ) & 0x00000002 ) | ( ( endPoint[1][1].b >> 2 ) & 0x00000004 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000003E); + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00000F80); + block.y |= ( endPoint[1][1].b << 18 ) & 0x00040000; + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001; + block.z |= ( ( endPoint[1][1].b << 9 ) & 0x00001000 ) | ( ( endPoint[1][1].b << 4 ) & 0x00000040 );*/ + + block.x |= ((candidateModeMemory[8] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[8] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[8] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[8] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[8] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0][0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0][0].r >> 7) & 1) << 12; + block.x |= ((endPoint[1][1].b >> 1) & 1) << 13; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0][0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0][0].g >> 7) & 1) << 22; + block.x |= ((endPoint[1][0].b >> 5) & 1) << 23; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0][0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0][0].b >> 7) & 1) << 0; + block.y |= ((endPoint[1][1].b >> 5) & 1) << 1; + block.y |= ((endPoint[1][1].b >> 4) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1][1].g >> 4) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1][1].b >> 0) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[0][1].b >> 5) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][1].b >> 2) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].b >> 3) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } + else if ( mode_type == candidateModeFlag[9]) + { + /*block.x = candidateModeMemory[9]; + block.x |= ( ( endPoint[0][0].r << 5 ) & 0x000007E0 ) | ( ( endPoint[0][0].g << 15 ) & 0x001F8000 ) | ( ( endPoint[0][0].b << 25 ) & 0x7E000000 ); + block.y |= ( ( endPoint[0][1].r << 3 ) & 0x000001F8 ) | ( ( endPoint[0][1].g << 13 ) & 0x0007E000 ) | ( ( endPoint[0][1].b << 23 ) & 0x1F800000 ); + block.x |= ( ( endPoint[1][0].g << 16 ) & 0x00200000 ) | ( ( endPoint[1][0].g << 20 ) & 0x01000000 ); + block.x |= ( ( endPoint[1][0].b << 17 ) & 0x00400000 ) | ( ( endPoint[1][0].b << 10 ) & 0x00004000 ); + block.x |= ( ( endPoint[1][1].b << 21 ) & 0x00800000 ) | ( ( endPoint[1][1].b << 12 ) & 0x00003000 ); + block.x |= ( ( endPoint[1][1].g << 26 ) & 0x80000000 ) | ( ( endPoint[1][1].g << 7 ) & 0x00000800 ); + block.yz |= ( endPoint[1][0].gr << uint2(9, 1) ) & uint2(0x00001E00, 0x0000007E); + block.yz |= ( endPoint[1][1].gr << uint2(19, 7) ) & uint2(0x00780000, 0x00001F80); + block.y |= ( endPoint[1][0].b << 29 ) & 0xE0000000; + block.y |= ( ( endPoint[1][1].b >> 4 ) & 0x00000002 ) | ( ( endPoint[1][1].b >> 2 ) & 0x00000004 ) | ( ( endPoint[1][1].b >> 3 ) & 0x00000001 ); + block.z |= ( endPoint[1][0].b >> 3 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[9] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[9] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[9] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[9] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[9] >> 4) & 1) << 4; + block.x |= ((endPoint[0][0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0][0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0][0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0][0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0][0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0][0].r >> 5) & 1) << 10; + block.x |= ((endPoint[1][1].g >> 4) & 1) << 11; + block.x |= ((endPoint[1][1].b >> 0) & 1) << 12; + block.x |= ((endPoint[1][1].b >> 1) & 1) << 13; + block.x |= ((endPoint[1][0].b >> 4) & 1) << 14; + block.x |= ((endPoint[0][0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0][0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0][0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0][0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0][0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0][0].g >> 5) & 1) << 20; + block.x |= ((endPoint[1][0].g >> 5) & 1) << 21; + block.x |= ((endPoint[1][0].b >> 5) & 1) << 22; + block.x |= ((endPoint[1][1].b >> 2) & 1) << 23; + block.x |= ((endPoint[1][0].g >> 4) & 1) << 24; + block.x |= ((endPoint[0][0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0][0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0][0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0][0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0][0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0][0].b >> 5) & 1) << 30; + block.x |= ((endPoint[1][1].g >> 5) & 1) << 31; + block.y |= ((endPoint[1][1].b >> 3) & 1) << 0; + block.y |= ((endPoint[1][1].b >> 5) & 1) << 1; + block.y |= ((endPoint[1][1].b >> 4) & 1) << 2; + block.y |= ((endPoint[0][1].r >> 0) & 1) << 3; + block.y |= ((endPoint[0][1].r >> 1) & 1) << 4; + block.y |= ((endPoint[0][1].r >> 2) & 1) << 5; + block.y |= ((endPoint[0][1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0][1].r >> 4) & 1) << 7; + block.y |= ((endPoint[0][1].r >> 5) & 1) << 8; + block.y |= ((endPoint[1][0].g >> 0) & 1) << 9; + block.y |= ((endPoint[1][0].g >> 1) & 1) << 10; + block.y |= ((endPoint[1][0].g >> 2) & 1) << 11; + block.y |= ((endPoint[1][0].g >> 3) & 1) << 12; + block.y |= ((endPoint[0][1].g >> 0) & 1) << 13; + block.y |= ((endPoint[0][1].g >> 1) & 1) << 14; + block.y |= ((endPoint[0][1].g >> 2) & 1) << 15; + block.y |= ((endPoint[0][1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0][1].g >> 4) & 1) << 17; + block.y |= ((endPoint[0][1].g >> 5) & 1) << 18; + block.y |= ((endPoint[1][1].g >> 0) & 1) << 19; + block.y |= ((endPoint[1][1].g >> 1) & 1) << 20; + block.y |= ((endPoint[1][1].g >> 2) & 1) << 21; + block.y |= ((endPoint[1][1].g >> 3) & 1) << 22; + block.y |= ((endPoint[0][1].b >> 0) & 1) << 23; + block.y |= ((endPoint[0][1].b >> 1) & 1) << 24; + block.y |= ((endPoint[0][1].b >> 2) & 1) << 25; + block.y |= ((endPoint[0][1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0][1].b >> 4) & 1) << 27; + block.y |= ((endPoint[0][1].b >> 5) & 1) << 28; + block.y |= ((endPoint[1][0].b >> 0) & 1) << 29; + block.y |= ((endPoint[1][0].b >> 1) & 1) << 30; + block.y |= ((endPoint[1][0].b >> 2) & 1) << 31; + block.z |= ((endPoint[1][0].b >> 3) & 1) << 0; + block.z |= ((endPoint[1][0].r >> 0) & 1) << 1; + block.z |= ((endPoint[1][0].r >> 1) & 1) << 2; + block.z |= ((endPoint[1][0].r >> 2) & 1) << 3; + block.z |= ((endPoint[1][0].r >> 3) & 1) << 4; + block.z |= ((endPoint[1][0].r >> 4) & 1) << 5; + block.z |= ((endPoint[1][0].r >> 5) & 1) << 6; + block.z |= ((endPoint[1][1].r >> 0) & 1) << 7; + block.z |= ((endPoint[1][1].r >> 1) & 1) << 8; + block.z |= ((endPoint[1][1].r >> 2) & 1) << 9; + block.z |= ((endPoint[1][1].r >> 3) & 1) << 10; + block.z |= ((endPoint[1][1].r >> 4) & 1) << 11; + block.z |= ((endPoint[1][1].r >> 5) & 1) << 12; + block.z |= ((partition_index >> 0) & 1) << 13; + block.z |= ((partition_index >> 1) & 1) << 14; + block.z |= ((partition_index >> 2) & 1) << 15; + block.z |= ((partition_index >> 3) & 1) << 16; + block.z |= ((partition_index >> 4) & 1) << 17; + } +} +void block_package( inout uint4 block, int2x3 endPoint, uint mode_type ) // for mode 11 - 14 +{ + /*block.x = ( ( endPoint[0].r << 5 ) & 0x00007FE0 ) | ( ( endPoint[0].g << 15 ) & 0x01FF8000 ) | ( ( endPoint[0].b << 25 ) & 0xFE000000 ); + block.y |= ( endPoint[0].b >> 7 ) & 0x00000007;*/ + + block.xy = 0; + block.z &= 0xFFFFFFFE; + + + if ( mode_type == candidateModeFlag[10]) + { + /* block.x |= candidateModeMemory[10]; + block.y |= ( ( endPoint[1].r << 3 ) & 0x00001FF8 ) | ( ( endPoint[1].g << 13 ) & 0x007FE000 ) | ( ( endPoint[1].b << 23 ) & 0xFF800000 ); + block.z |= ( endPoint[1].b >> 9 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[10] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[10] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[10] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[10] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[10] >> 4) & 1) << 4; + block.x |= ((endPoint[0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0].b >> 9) & 1) << 2; + block.y |= ((endPoint[1].r >> 0) & 1) << 3; + block.y |= ((endPoint[1].r >> 1) & 1) << 4; + block.y |= ((endPoint[1].r >> 2) & 1) << 5; + block.y |= ((endPoint[1].r >> 3) & 1) << 6; + block.y |= ((endPoint[1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1].r >> 5) & 1) << 8; + block.y |= ((endPoint[1].r >> 6) & 1) << 9; + block.y |= ((endPoint[1].r >> 7) & 1) << 10; + block.y |= ((endPoint[1].r >> 8) & 1) << 11; + block.y |= ((endPoint[1].r >> 9) & 1) << 12; + block.y |= ((endPoint[1].g >> 0) & 1) << 13; + block.y |= ((endPoint[1].g >> 1) & 1) << 14; + block.y |= ((endPoint[1].g >> 2) & 1) << 15; + block.y |= ((endPoint[1].g >> 3) & 1) << 16; + block.y |= ((endPoint[1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1].g >> 5) & 1) << 18; + block.y |= ((endPoint[1].g >> 6) & 1) << 19; + block.y |= ((endPoint[1].g >> 7) & 1) << 20; + block.y |= ((endPoint[1].g >> 8) & 1) << 21; + block.y |= ((endPoint[1].g >> 9) & 1) << 22; + block.y |= ((endPoint[1].b >> 0) & 1) << 23; + block.y |= ((endPoint[1].b >> 1) & 1) << 24; + block.y |= ((endPoint[1].b >> 2) & 1) << 25; + block.y |= ((endPoint[1].b >> 3) & 1) << 26; + block.y |= ((endPoint[1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1].b >> 5) & 1) << 28; + block.y |= ((endPoint[1].b >> 6) & 1) << 29; + block.y |= ((endPoint[1].b >> 7) & 1) << 30; + block.y |= ((endPoint[1].b >> 8) & 1) << 31; + block.z |= ((endPoint[1].b >> 9) & 1) << 0; + } + else if (mode_type == candidateModeFlag[11]) + { + /*block.x |= candidateModeMemory[11]; + block.y |= ( ( endPoint[0].r << 2 ) & 0x00001000 ) | ( ( endPoint[0].g << 12 ) & 0x00400000 ); + block.y |= ( ( endPoint[1].r << 3 ) & 0x00000FF8 ) | ( ( endPoint[1].g << 13 ) & 0x003FE000 ) | ( ( endPoint[1].b << 23 ) & 0xFF800000 ); + block.z |= ( endPoint[0].b >> 10 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[11] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[11] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[11] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[11] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[11] >> 4) & 1) << 4; + block.x |= ((endPoint[0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0].b >> 9) & 1) << 2; + block.y |= ((endPoint[1].r >> 0) & 1) << 3; + block.y |= ((endPoint[1].r >> 1) & 1) << 4; + block.y |= ((endPoint[1].r >> 2) & 1) << 5; + block.y |= ((endPoint[1].r >> 3) & 1) << 6; + block.y |= ((endPoint[1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1].r >> 5) & 1) << 8; + block.y |= ((endPoint[1].r >> 6) & 1) << 9; + block.y |= ((endPoint[1].r >> 7) & 1) << 10; + block.y |= ((endPoint[1].r >> 8) & 1) << 11; + block.y |= ((endPoint[0].r >> 10) & 1) << 12; + block.y |= ((endPoint[1].g >> 0) & 1) << 13; + block.y |= ((endPoint[1].g >> 1) & 1) << 14; + block.y |= ((endPoint[1].g >> 2) & 1) << 15; + block.y |= ((endPoint[1].g >> 3) & 1) << 16; + block.y |= ((endPoint[1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1].g >> 5) & 1) << 18; + block.y |= ((endPoint[1].g >> 6) & 1) << 19; + block.y |= ((endPoint[1].g >> 7) & 1) << 20; + block.y |= ((endPoint[1].g >> 8) & 1) << 21; + block.y |= ((endPoint[0].g >> 10) & 1) << 22; + block.y |= ((endPoint[1].b >> 0) & 1) << 23; + block.y |= ((endPoint[1].b >> 1) & 1) << 24; + block.y |= ((endPoint[1].b >> 2) & 1) << 25; + block.y |= ((endPoint[1].b >> 3) & 1) << 26; + block.y |= ((endPoint[1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1].b >> 5) & 1) << 28; + block.y |= ((endPoint[1].b >> 6) & 1) << 29; + block.y |= ((endPoint[1].b >> 7) & 1) << 30; + block.y |= ((endPoint[1].b >> 8) & 1) << 31; + block.z |= ((endPoint[0].b >> 10) & 1) << 0; + } + else if (mode_type == candidateModeFlag[12])// violate the spec in [0].low + { + /*block.x |= candidateModeMemory[12]; + block.y |= ( ( endPoint[0].r << 2 ) & 0x00001000 ) | ( ( endPoint[0].g << 12 ) & 0x00400000 ); + block.y |= ( ( endPoint[0].r << 0 ) & 0x00000800 ) | ( ( endPoint[0].g << 10 ) & 0x00200000 ); + block.y |= ( endPoint[0].b << 20 ) & 0x80000000; + block.y |= ( ( endPoint[1].r << 3 ) & 0x000007F8 ) | ( ( endPoint[1].g << 13 ) & 0x001FE000 ) | ( ( endPoint[1].b << 23 ) & 0x7F800000 ); + block.z |= ( endPoint[0].b >> 10 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[12] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[12] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[12] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[12] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[12] >> 4) & 1) << 4; + block.x |= ((endPoint[0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0].b >> 9) & 1) << 2; + block.y |= ((endPoint[1].r >> 0) & 1) << 3; + block.y |= ((endPoint[1].r >> 1) & 1) << 4; + block.y |= ((endPoint[1].r >> 2) & 1) << 5; + block.y |= ((endPoint[1].r >> 3) & 1) << 6; + block.y |= ((endPoint[1].r >> 4) & 1) << 7; + block.y |= ((endPoint[1].r >> 5) & 1) << 8; + block.y |= ((endPoint[1].r >> 6) & 1) << 9; + block.y |= ((endPoint[1].r >> 7) & 1) << 10; + block.y |= ((endPoint[0].r >> 11) & 1) << 11; + block.y |= ((endPoint[0].r >> 10) & 1) << 12; + block.y |= ((endPoint[1].g >> 0) & 1) << 13; + block.y |= ((endPoint[1].g >> 1) & 1) << 14; + block.y |= ((endPoint[1].g >> 2) & 1) << 15; + block.y |= ((endPoint[1].g >> 3) & 1) << 16; + block.y |= ((endPoint[1].g >> 4) & 1) << 17; + block.y |= ((endPoint[1].g >> 5) & 1) << 18; + block.y |= ((endPoint[1].g >> 6) & 1) << 19; + block.y |= ((endPoint[1].g >> 7) & 1) << 20; + block.y |= ((endPoint[0].g >> 11) & 1) << 21; + block.y |= ((endPoint[0].g >> 10) & 1) << 22; + block.y |= ((endPoint[1].b >> 0) & 1) << 23; + block.y |= ((endPoint[1].b >> 1) & 1) << 24; + block.y |= ((endPoint[1].b >> 2) & 1) << 25; + block.y |= ((endPoint[1].b >> 3) & 1) << 26; + block.y |= ((endPoint[1].b >> 4) & 1) << 27; + block.y |= ((endPoint[1].b >> 5) & 1) << 28; + block.y |= ((endPoint[1].b >> 6) & 1) << 29; + block.y |= ((endPoint[1].b >> 7) & 1) << 30; + block.y |= ((endPoint[0].b >> 11) & 1) << 31; + block.z |= ((endPoint[0].b >> 10) & 1) << 0; + } + else if (mode_type == candidateModeFlag[13]) + { + /*block.x |= candidateModeMemory[13]; + block.y |= ( ( endPoint[0].r >> 8 ) & 0x00000080 ); + block.y |= ( ( endPoint[0].r >> 6 ) & 0x00000100 ); + block.y |= ( ( endPoint[0].r >> 4 ) & 0x00000200 ); + block.y |= ( ( endPoint[0].r >> 2 ) & 0x00000400 ); + block.y |= ( ( endPoint[0].r >> 0 ) & 0x00000800 ); + block.y |= ( ( endPoint[0].r << 2 ) & 0x00001000 ); + block.y |= ( ( endPoint[0].g << 2 ) & 0x00020000 ); + block.y |= ( ( endPoint[0].g << 4 ) & 0x00040000 ); + block.y |= ( ( endPoint[0].g << 6 ) & 0x00080000 ); + block.y |= ( ( endPoint[0].g << 8 ) & 0x00100000 ); + block.y |= ( ( endPoint[0].g << 10 ) & 0x00200000 ); + block.y |= ( ( endPoint[0].g << 12 ) & 0x00400000 ); + block.y |= ( ( endPoint[0].b << 12 ) & 0x08000000 ); + block.y |= ( ( endPoint[0].b << 14 ) & 0x10000000 ); + block.y |= ( ( endPoint[0].b << 16 ) & 0x20000000 ); + block.y |= ( ( endPoint[0].b << 18 ) & 0x40000000 ); + block.y |= ( ( endPoint[0].b << 20 ) & 0x80000000 ); + block.y |= ( ( endPoint[1].r << 3 ) & 0x00000078 ) | ( ( endPoint[1].g << 13 ) & 0x0001E000 ) | ( ( endPoint[1].b << 23 ) & 0x07800000 ); + block.z |= ( endPoint[0].b >> 10 ) & 0x00000001;*/ + + block.x |= ((candidateModeMemory[13] >> 0) & 1) << 0; + block.x |= ((candidateModeMemory[13] >> 1) & 1) << 1; + block.x |= ((candidateModeMemory[13] >> 2) & 1) << 2; + block.x |= ((candidateModeMemory[13] >> 3) & 1) << 3; + block.x |= ((candidateModeMemory[13] >> 4) & 1) << 4; + block.x |= ((endPoint[0].r >> 0) & 1) << 5; + block.x |= ((endPoint[0].r >> 1) & 1) << 6; + block.x |= ((endPoint[0].r >> 2) & 1) << 7; + block.x |= ((endPoint[0].r >> 3) & 1) << 8; + block.x |= ((endPoint[0].r >> 4) & 1) << 9; + block.x |= ((endPoint[0].r >> 5) & 1) << 10; + block.x |= ((endPoint[0].r >> 6) & 1) << 11; + block.x |= ((endPoint[0].r >> 7) & 1) << 12; + block.x |= ((endPoint[0].r >> 8) & 1) << 13; + block.x |= ((endPoint[0].r >> 9) & 1) << 14; + block.x |= ((endPoint[0].g >> 0) & 1) << 15; + block.x |= ((endPoint[0].g >> 1) & 1) << 16; + block.x |= ((endPoint[0].g >> 2) & 1) << 17; + block.x |= ((endPoint[0].g >> 3) & 1) << 18; + block.x |= ((endPoint[0].g >> 4) & 1) << 19; + block.x |= ((endPoint[0].g >> 5) & 1) << 20; + block.x |= ((endPoint[0].g >> 6) & 1) << 21; + block.x |= ((endPoint[0].g >> 7) & 1) << 22; + block.x |= ((endPoint[0].g >> 8) & 1) << 23; + block.x |= ((endPoint[0].g >> 9) & 1) << 24; + block.x |= ((endPoint[0].b >> 0) & 1) << 25; + block.x |= ((endPoint[0].b >> 1) & 1) << 26; + block.x |= ((endPoint[0].b >> 2) & 1) << 27; + block.x |= ((endPoint[0].b >> 3) & 1) << 28; + block.x |= ((endPoint[0].b >> 4) & 1) << 29; + block.x |= ((endPoint[0].b >> 5) & 1) << 30; + block.x |= ((endPoint[0].b >> 6) & 1) << 31; + block.y |= ((endPoint[0].b >> 7) & 1) << 0; + block.y |= ((endPoint[0].b >> 8) & 1) << 1; + block.y |= ((endPoint[0].b >> 9) & 1) << 2; + block.y |= ((endPoint[1].r >> 0) & 1) << 3; + block.y |= ((endPoint[1].r >> 1) & 1) << 4; + block.y |= ((endPoint[1].r >> 2) & 1) << 5; + block.y |= ((endPoint[1].r >> 3) & 1) << 6; + block.y |= ((endPoint[0].r >> 15) & 1) << 7; + block.y |= ((endPoint[0].r >> 14) & 1) << 8; + block.y |= ((endPoint[0].r >> 13) & 1) << 9; + block.y |= ((endPoint[0].r >> 12) & 1) << 10; + block.y |= ((endPoint[0].r >> 11) & 1) << 11; + block.y |= ((endPoint[0].r >> 10) & 1) << 12; + block.y |= ((endPoint[1].g >> 0) & 1) << 13; + block.y |= ((endPoint[1].g >> 1) & 1) << 14; + block.y |= ((endPoint[1].g >> 2) & 1) << 15; + block.y |= ((endPoint[1].g >> 3) & 1) << 16; + block.y |= ((endPoint[0].g >> 15) & 1) << 17; + block.y |= ((endPoint[0].g >> 14) & 1) << 18; + block.y |= ((endPoint[0].g >> 13) & 1) << 19; + block.y |= ((endPoint[0].g >> 12) & 1) << 20; + block.y |= ((endPoint[0].g >> 11) & 1) << 21; + block.y |= ((endPoint[0].g >> 10) & 1) << 22; + block.y |= ((endPoint[1].b >> 0) & 1) << 23; + block.y |= ((endPoint[1].b >> 1) & 1) << 24; + block.y |= ((endPoint[1].b >> 2) & 1) << 25; + block.y |= ((endPoint[1].b >> 3) & 1) << 26; + block.y |= ((endPoint[0].b >> 15) & 1) << 27; + block.y |= ((endPoint[0].b >> 14) & 1) << 28; + block.y |= ((endPoint[0].b >> 13) & 1) << 29; + block.y |= ((endPoint[0].b >> 12) & 1) << 30; + block.y |= ((endPoint[0].b >> 11) & 1) << 31; + block.z |= ((endPoint[0].b >> 10) & 1) << 0; + } +} diff --git a/Kits/DirectXTex/Shaders/BC7Encode.hlsl b/Kits/DirectXTex/Shaders/BC7Encode.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..8f31c960a5fbbc54df80094e4c8c52b75f5abf83 --- /dev/null +++ b/Kits/DirectXTex/Shaders/BC7Encode.hlsl @@ -0,0 +1,1907 @@ +//-------------------------------------------------------------------------------------- +// File: BC7Encode.hlsl +// +// The Compute Shader for BC7 Encoder +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +//#define REF_DEVICE + +#define CHAR_LENGTH 8 +#define NCHANNELS 4 +#define BC7_UNORM 98 +#define MAX_UINT 0xFFFFFFFF +#define MIN_UINT 0 + +static const uint candidateSectionBit[64] = //Associated to partition 0-63 +{ + 0xCCCC, 0x8888, 0xEEEE, 0xECC8, + 0xC880, 0xFEEC, 0xFEC8, 0xEC80, + 0xC800, 0xFFEC, 0xFE80, 0xE800, + 0xFFE8, 0xFF00, 0xFFF0, 0xF000, + 0xF710, 0x008E, 0x7100, 0x08CE, + 0x008C, 0x7310, 0x3100, 0x8CCE, + 0x088C, 0x3110, 0x6666, 0x366C, + 0x17E8, 0x0FF0, 0x718E, 0x399C, + 0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, + 0x3c3c, 0x55aa, 0x9696, 0xa55a, + 0x73ce, 0x13c8, 0x324c, 0x3bdc, + 0x6996, 0xc33c, 0x9966, 0x660, + 0x272, 0x4e4, 0x4e40, 0x2720, + 0xc936, 0x936c, 0x39c6, 0x639c, + 0x9336, 0x9cc6, 0x817e, 0xe718, + 0xccf0, 0xfcc, 0x7744, 0xee22, +}; +static const uint candidateSectionBit2[64] = //Associated to partition 64-127 +{ + 0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8, + 0xa5a50000, 0xa0a05050, 0x5555a0a0, 0x5a5a5050, + 0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090, + 0x94949494, 0xa4a4a4a4, 0xa9a59450, 0x2a0a4250, + 0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0, + 0xa8a85454, 0x6a6a4040, 0xa4a45000, 0x1a1a0500, + 0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400, + 0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200, + 0xa9a58000, 0x5090a0a8, 0xa8a09050, 0x24242424, + 0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50, + 0x500aa550, 0xaaaa4444, 0x66660000, 0xa5a0a5a0, + 0x50a050a0, 0x69286928, 0x44aaaa44, 0x66666600, + 0xaa444444, 0x54a854a8, 0x95809580, 0x96969600, + 0xa85454a8, 0x80959580, 0xaa141414, 0x96960000, + 0xaaaa1414, 0xa05050a0, 0xa0a5a5a0, 0x96000000, + 0x40804080, 0xa9a8a9a8, 0xaaaaaa44, 0x2a4a5254, +}; +static const uint2 candidateFixUpIndex1D[128] = +{ + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{ 2, 0},{ 8, 0},{ 2, 0}, + { 2, 0},{ 8, 0},{ 8, 0},{15, 0}, + { 2, 0},{ 8, 0},{ 2, 0},{ 2, 0}, + { 8, 0},{ 8, 0},{ 2, 0},{ 2, 0}, + + {15, 0},{15, 0},{ 6, 0},{ 8, 0}, + { 2, 0},{ 8, 0},{15, 0},{15, 0}, + { 2, 0},{ 8, 0},{ 2, 0},{ 2, 0}, + { 2, 0},{15, 0},{15, 0},{ 6, 0}, + { 6, 0},{ 2, 0},{ 6, 0},{ 8, 0}, + {15, 0},{15, 0},{ 2, 0},{ 2, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{ 2, 0},{ 2, 0},{15, 0}, + //candidateFixUpIndex1D[i][1], i < 64 should not be used + + { 3,15},{ 3, 8},{15, 8},{15, 3}, + { 8,15},{ 3,15},{15, 3},{15, 8}, + { 8,15},{ 8,15},{ 6,15},{ 6,15}, + { 6,15},{ 5,15},{ 3,15},{ 3, 8}, + { 3,15},{ 3, 8},{ 8,15},{15, 3}, + { 3,15},{ 3, 8},{ 6,15},{10, 8}, + { 5, 3},{ 8,15},{ 8, 6},{ 6,10}, + { 8,15},{ 5,15},{15,10},{15, 8}, + + { 8,15},{15, 3},{ 3,15},{ 5,10}, + { 6,10},{10, 8},{ 8, 9},{15,10}, + {15, 6},{ 3,15},{15, 8},{ 5,15}, + {15, 3},{15, 6},{15, 6},{15, 8}, //The Spec doesn't mark the first fixed up index in this row, so I apply 15 for them, and seems correct + { 3,15},{15, 3},{ 5,15},{ 5,15}, + { 5,15},{ 8,15},{ 5,15},{10,15}, + { 5,15},{10,15},{ 8,15},{13,15}, + {15, 3},{12,15},{ 3,15},{ 3, 8}, +}; +static const uint2 candidateFixUpIndex1DOrdered[128] = //Same with candidateFixUpIndex1D but order the result when i >= 64 +{ + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{ 2, 0},{ 8, 0},{ 2, 0}, + { 2, 0},{ 8, 0},{ 8, 0},{15, 0}, + { 2, 0},{ 8, 0},{ 2, 0},{ 2, 0}, + { 8, 0},{ 8, 0},{ 2, 0},{ 2, 0}, + + {15, 0},{15, 0},{ 6, 0},{ 8, 0}, + { 2, 0},{ 8, 0},{15, 0},{15, 0}, + { 2, 0},{ 8, 0},{ 2, 0},{ 2, 0}, + { 2, 0},{15, 0},{15, 0},{ 6, 0}, + { 6, 0},{ 2, 0},{ 6, 0},{ 8, 0}, + {15, 0},{15, 0},{ 2, 0},{ 2, 0}, + {15, 0},{15, 0},{15, 0},{15, 0}, + {15, 0},{ 2, 0},{ 2, 0},{15, 0}, + //candidateFixUpIndex1DOrdered[i][1], i < 64 should not be used + + { 3,15},{ 3, 8},{ 8,15},{ 3,15}, + { 8,15},{ 3,15},{ 3,15},{ 8,15}, + { 8,15},{ 8,15},{ 6,15},{ 6,15}, + { 6,15},{ 5,15},{ 3,15},{ 3, 8}, + { 3,15},{ 3, 8},{ 8,15},{ 3,15}, + { 3,15},{ 3, 8},{ 6,15},{ 8,10}, + { 3, 5},{ 8,15},{ 6, 8},{ 6,10}, + { 8,15},{ 5,15},{10,15},{ 8,15}, + + { 8,15},{ 3,15},{ 3,15},{ 5,10}, + { 6,10},{ 8,10},{ 8, 9},{10,15}, + { 6,15},{ 3,15},{ 8,15},{ 5,15}, + { 3,15},{ 6,15},{ 6,15},{ 8,15}, //The Spec doesn't mark the first fixed up index in this row, so I apply 15 for them, and seems correct + { 3,15},{ 3,15},{ 5,15},{ 5,15}, + { 5,15},{ 8,15},{ 5,15},{10,15}, + { 5,15},{10,15},{ 8,15},{13,15}, + { 3,15},{12,15},{ 3,15},{ 3, 8}, +}; +//static const uint4x4 candidateRotation[4] = +//{ +// {1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}, +// {0,0,0,1},{0,1,0,0},{0,0,1,0},{1,0,0,0}, +// {1,0,0,0},{0,0,0,1},{0,0,1,0},{0,1,0,0}, +// {1,0,0,0},{0,1,0,0},{0,0,0,1},{0,0,1,0} +//}; +//static const uint2 candidateIndexPrec[8] = {{3,0},{3,0},{2,0},{2,0}, +// {2,3}, //color index and alpha index can exchange +// {2,2},{4,4},{2,2}}; + +static const uint aWeight[3][16] = { {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64}, + {0, 9, 18, 27, 37, 46, 55, 64, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 21, 43, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + + //4 bit index: 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 +static const uint aStep[3][64] = { { 0, 0, 0, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, + 9,10,10,10,10,10,11,11, + 11,11,12,12,12,12,13,13, + 13,13,14,14,14,14,15,15 }, + //3 bit index: 0, 9, 18, 27, 37, 46, 55, 64 + { 0,0,0,0,0,1,1,1, + 1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,3, + 3,3,3,3,3,3,3,3, + 3,4,4,4,4,4,4,4, + 4,4,5,5,5,5,5,5, + 5,5,5,6,6,6,6,6, + 6,6,6,6,7,7,7,7 }, + //2 bit index: 0, 21, 43, 64 + { 0,0,0,0,0,0,0,0, + 0,0,0,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,3,3, + 3,3,3,3,3,3,3,3 } }; + +cbuffer cbCS : register( b0 ) +{ + uint g_tex_width; + uint g_num_block_x; + uint g_format; + uint g_mode_id; + uint g_start_block_id; + uint g_num_total_blocks; + float g_alpha_weight; +}; + +//Forward declaration +uint2x4 compress_endpoints0( inout uint2x4 endPoint, uint2 P ); //Mode = 0 +uint2x4 compress_endpoints1( inout uint2x4 endPoint, uint2 P ); //Mode = 1 +uint2x4 compress_endpoints2( inout uint2x4 endPoint ); //Mode = 2 +uint2x4 compress_endpoints3( inout uint2x4 endPoint, uint2 P ); //Mode = 3 +uint2x4 compress_endpoints7( inout uint2x4 endPoint, uint2 P ); //Mode = 7 +uint2x4 compress_endpoints6( inout uint2x4 endPoint, uint2 P ); //Mode = 6 +uint2x4 compress_endpoints4( inout uint2x4 endPoint ); //Mode = 4 +uint2x4 compress_endpoints5( inout uint2x4 endPoint ); //Mode = 5 + +void block_package0( out uint4 block, uint partition, uint threadBase ); //Mode0 +void block_package1( out uint4 block, uint partition, uint threadBase ); //Mode1 +void block_package2( out uint4 block, uint partition, uint threadBase ); //Mode2 +void block_package3( out uint4 block, uint partition, uint threadBase ); //Mode3 +void block_package4( out uint4 block, uint rotation, uint index_selector, uint threadBase ); //Mode4 +void block_package5( out uint4 block, uint rotation, uint threadBase ); //Mode5 +void block_package6( out uint4 block, uint threadBase ); //Mode6 +void block_package7( out uint4 block, uint partition, uint threadBase ); //Mode7 + + +void swap(inout uint4 lhs, inout uint4 rhs) +{ + uint4 tmp = lhs; + lhs = rhs; + rhs = tmp; +} +void swap(inout uint3 lhs, inout uint3 rhs) +{ + uint3 tmp = lhs; + lhs = rhs; + rhs = tmp; +} +void swap(inout uint lhs, inout uint rhs) +{ + uint tmp = lhs; + lhs = rhs; + rhs = tmp; +} + +uint ComputeError(in uint4 a, in uint4 b) +{ + return dot(a.rgb, b.rgb) + g_alpha_weight * a.a*b.a; +} + +void Ensure_A_Is_Larger( inout uint4 a, inout uint4 b ) +{ + if ( a.x < b.x ) + swap( a.x, b.x ); + if ( a.y < b.y ) + swap( a.y, b.y ); + if ( a.z < b.z ) + swap( a.z, b.z ); + if ( a.w < b.w ) + swap( a.w, b.w ); +} + + +Texture2D g_Input : register( t0 ); +StructuredBuffer g_InBuff : register( t1 ); + +RWStructuredBuffer g_OutBuff : register( u0 ); + +#define THREAD_GROUP_SIZE 64 +#define BLOCK_SIZE_Y 4 +#define BLOCK_SIZE_X 4 +#define BLOCK_SIZE (BLOCK_SIZE_Y * BLOCK_SIZE_X) + +struct BufferShared +{ + uint4 pixel; + uint error; + uint mode; + uint partition; + uint index_selector; + uint rotation; + uint4 endPoint_low; + uint4 endPoint_high; + uint4 endPoint_low_quantized; + uint4 endPoint_high_quantized; +}; +groupshared BufferShared shared_temp[THREAD_GROUP_SIZE]; + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void TryMode456CS( uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID ) // mode 4 5 6 all have 1 subset per block, and fix-up index is always index 0 +{ + // we process 4 BC blocks per thread group + const uint MAX_USED_THREAD = 16; // pixels in a BC (block compressed) block + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; // the number of BC blocks a thread group processes = 64 / 16 = 4 + uint blockInGroup = GI / MAX_USED_THREAD; // what BC block this thread is on within this thread group + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; // what global BC block this thread is on + uint threadBase = blockInGroup * MAX_USED_THREAD; // the first id of the pixel in this BC block in this thread group + uint threadInBlock = GI - threadBase; // id of the pixel in this BC block + +#ifndef REF_DEVICE + if (blockID >= g_num_total_blocks) + { + return; + } +#endif + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + if (threadInBlock < 16) + { + shared_temp[GI].pixel = clamp(uint4(g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ) * 255), 0, 255); + + shared_temp[GI].endPoint_low = shared_temp[GI].pixel; + shared_temp[GI].endPoint_high = shared_temp[GI].pixel; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 8) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 8].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 8].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 4].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 4].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 2].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 2].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 1].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 1].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + uint2x4 endPoint; + endPoint[0] = shared_temp[threadBase].endPoint_low; + endPoint[1] = shared_temp[threadBase].endPoint_high; + + uint error = 0xFFFFFFFF; + uint mode = 0; + uint index_selector = 0; + uint rotation = 0; + + uint2 indexPrec; + if (threadInBlock < 8) // all threads of threadInBlock < 8 will be working on trying out mode 4, since only mode 4 has index selector bit + { + if (0 == (threadInBlock & 1)) // thread 0, 2, 4, 6 + { + //2 represents 2bit index precision; 1 represents 3bit index precision + index_selector = 0; + indexPrec = uint2( 2, 1 ); + } + else // thread 1, 3, 5, 7 + { + //2 represents 2bit index precision; 1 represents 3bit index precision + index_selector = 1; + indexPrec = uint2( 1, 2 ); + } + } + else + { + //2 represents 2bit index precision + indexPrec = uint2( 2, 2 ); + } + + uint4 pixel_r; + uint color_index; + uint alpha_index; + int4 span; + int2 span_norm_sqr; + int2 dotProduct; + if (threadInBlock < 12) // Try mode 4 5 in threads 0..11 + { + // mode 4 5 have component rotation + if ((threadInBlock < 2) || (8 == threadInBlock)) // rotation = 0 in thread 0, 1 + { + rotation = 0; + } + else if ((threadInBlock < 4) || (9 == threadInBlock)) // rotation = 1 in thread 2, 3 + { + endPoint[0].ra = endPoint[0].ar; + endPoint[1].ra = endPoint[1].ar; + + rotation = 1; + } + else if ((threadInBlock < 6) || (10 == threadInBlock)) // rotation = 2 in thread 4, 5 + { + endPoint[0].ga = endPoint[0].ag; + endPoint[1].ga = endPoint[1].ag; + + rotation = 2; + } + else if ((threadInBlock < 8) || (11 == threadInBlock)) // rotation = 3 in thread 6, 7 + { + endPoint[0].ba = endPoint[0].ab; + endPoint[1].ba = endPoint[1].ab; + + rotation = 3; + } + + if (threadInBlock < 8) // try mode 4 in threads 0..7 + { + // mode 4 thread distribution + // Thread 0 1 2 3 4 5 6 7 + // Rotation 0 0 1 1 2 2 3 3 + // Index selector 0 1 0 1 0 1 0 1 + + mode = 4; + compress_endpoints4( endPoint ); + } + else // try mode 5 in threads 8..11 + { + // mode 5 thread distribution + // Thread 8 9 10 11 + // Rotation 0 1 2 3 + + mode = 5; + compress_endpoints5( endPoint ); + } + + uint4 pixel = shared_temp[threadBase + 0].pixel; + if (1 == rotation) + { + pixel.ra = pixel.ar; + } + else if (2 == rotation) + { + pixel.ga = pixel.ag; + } + else if (3 == rotation) + { + pixel.ba = pixel.ab; + } + + span = endPoint[1] - endPoint[0]; + span_norm_sqr = uint2( dot( span.rgb, span.rgb ), span.a * span.a ); + + // in mode 4 5 6, end point 0 must be closer to pixel 0 than end point 1, because of the fix-up index is always index 0 + // TODO: this shouldn't be necessary here in error calculation + /* + dotProduct = int2( dot( span.rgb, pixel.rgb - endPoint[0].rgb ), span.a * ( pixel.a - endPoint[0].a ) ); + if ( span_norm_sqr.x > 0 && dotProduct.x > 0 && uint( dotProduct.x * 63.49999 ) > uint( 32 * span_norm_sqr.x ) ) + { + span.rgb = -span.rgb; + swap(endPoint[0].rgb, endPoint[1].rgb); + } + if ( span_norm_sqr.y > 0 && dotProduct.y > 0 && uint( dotProduct.y * 63.49999 ) > uint( 32 * span_norm_sqr.y ) ) + { + span.a = -span.a; + swap(endPoint[0].a, endPoint[1].a); + } + */ + + // should be the same as above + dotProduct = int2( dot( pixel.rgb - endPoint[0].rgb, pixel.rgb - endPoint[0].rgb ), dot( pixel.rgb - endPoint[1].rgb, pixel.rgb - endPoint[1].rgb ) ); + if ( dotProduct.x > dotProduct.y ) + { + span.rgb = -span.rgb; + swap(endPoint[0].rgb, endPoint[1].rgb); + } + dotProduct = int2( dot( pixel.a - endPoint[0].a, pixel.a - endPoint[0].a ), dot( pixel.a - endPoint[1].a, pixel.a - endPoint[1].a ) ); + if ( dotProduct.x > dotProduct.y ) + { + span.a = -span.a; + swap(endPoint[0].a, endPoint[1].a); + } + + error = 0; + for ( uint i = 0; i < 16; i ++ ) + { + pixel = shared_temp[threadBase + i].pixel; + if (1 == rotation) + { + pixel.ra = pixel.ar; + } + else if (2 == rotation) + { + pixel.ga = pixel.ag; + } + else if (3 == rotation) + { + pixel.ba = pixel.ab; + } + + dotProduct.x = dot( span.rgb, pixel.rgb - endPoint[0].rgb ); + color_index = ( span_norm_sqr.x <= 0 /*endPoint[0] == endPoint[1]*/ || dotProduct.x <= 0 /*pixel == endPoint[0]*/ ) ? 0 + : ( ( dotProduct.x < span_norm_sqr.x ) ? aStep[indexPrec.x][ uint( dotProduct.x * 63.49999 / span_norm_sqr.x ) ] : aStep[indexPrec.x][63] ); + dotProduct.y = dot( span.a, pixel.a - endPoint[0].a ); + alpha_index = ( span_norm_sqr.y <= 0 || dotProduct.y <= 0 ) ? 0 + : ( ( dotProduct.y < span_norm_sqr.y ) ? aStep[indexPrec.y][ uint( dotProduct.y * 63.49999 / span_norm_sqr.y ) ] : aStep[indexPrec.y][63] ); + + // the same color_index and alpha_index should be used for reconstruction, so this should be left commented out + /*if (index_selector) + { + swap(color_index, alpha_index); + }*/ + + pixel_r.rgb = ( ( 64 - aWeight[indexPrec.x][color_index] ) * endPoint[0].rgb + + aWeight[indexPrec.x][color_index] * endPoint[1].rgb + + 32 ) >> 6; + pixel_r.a = ( ( 64 - aWeight[indexPrec.y][alpha_index] ) * endPoint[0].a + + aWeight[indexPrec.y][alpha_index] * endPoint[1].a + + 32 ) >> 6; + + Ensure_A_Is_Larger( pixel_r, pixel ); + pixel_r -= pixel; + if (1 == rotation) + { + pixel_r.ra = pixel_r.ar; + } + else if (2 == rotation) + { + pixel_r.ga = pixel_r.ag; + } + else if (3 == rotation) + { + pixel_r.ba = pixel_r.ab; + } + error += ComputeError(pixel_r, pixel_r); + } + } + else if (threadInBlock < 16) // Try mode 6 in threads 12..15, since in mode 4 5 6, only mode 6 has p bit + { + uint p = threadInBlock - 12; + + compress_endpoints6( endPoint, uint2(p >> 0, p >> 1) & 1 ); + + uint4 pixel = shared_temp[threadBase + 0].pixel; + + span = endPoint[1] - endPoint[0]; + span_norm_sqr = dot( span, span ); + dotProduct = dot( span, pixel - endPoint[0] ); + if ( span_norm_sqr.x > 0 && dotProduct.x >= 0 && uint( dotProduct.x * 63.49999 ) > uint( 32 * span_norm_sqr.x ) ) + { + span = -span; + swap(endPoint[0], endPoint[1]); + } + + error = 0; + for ( uint i = 0; i < 16; i ++ ) + { + pixel = shared_temp[threadBase + i].pixel; + + dotProduct.x = dot( span, pixel - endPoint[0] ); + color_index = ( span_norm_sqr.x <= 0 || dotProduct.x <= 0 ) ? 0 + : ( ( dotProduct.x < span_norm_sqr.x ) ? aStep[0][ uint( dotProduct.x * 63.49999 / span_norm_sqr.x ) ] : aStep[0][63] ); + + pixel_r = ( ( 64 - aWeight[0][color_index] ) * endPoint[0] + + aWeight[0][color_index] * endPoint[1] + 32 ) >> 6; + + Ensure_A_Is_Larger( pixel_r, pixel ); + pixel_r -= pixel; + error += ComputeError(pixel_r, pixel_r); + } + + mode = 6; + rotation = p; // Borrow rotation for p + } + + shared_temp[GI].error = error; + shared_temp[GI].mode = mode; + shared_temp[GI].index_selector = index_selector; + shared_temp[GI].rotation = rotation; + +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 8) + { + if ( shared_temp[GI].error > shared_temp[GI + 8].error ) + { + shared_temp[GI].error = shared_temp[GI + 8].error; + shared_temp[GI].mode = shared_temp[GI + 8].mode; + shared_temp[GI].index_selector = shared_temp[GI + 8].index_selector; + shared_temp[GI].rotation = shared_temp[GI + 8].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + if ( shared_temp[GI].error > shared_temp[GI + 4].error ) + { + shared_temp[GI].error = shared_temp[GI + 4].error; + shared_temp[GI].mode = shared_temp[GI + 4].mode; + shared_temp[GI].index_selector = shared_temp[GI + 4].index_selector; + shared_temp[GI].rotation = shared_temp[GI + 4].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + if ( shared_temp[GI].error > shared_temp[GI + 2].error ) + { + shared_temp[GI].error = shared_temp[GI + 2].error; + shared_temp[GI].mode = shared_temp[GI + 2].mode; + shared_temp[GI].index_selector = shared_temp[GI + 2].index_selector; + shared_temp[GI].rotation = shared_temp[GI + 2].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + if ( shared_temp[GI].error > shared_temp[GI + 1].error ) + { + shared_temp[GI].error = shared_temp[GI + 1].error; + shared_temp[GI].mode = shared_temp[GI + 1].mode; + shared_temp[GI].index_selector = shared_temp[GI + 1].index_selector; + shared_temp[GI].rotation = shared_temp[GI + 1].rotation; + } + + g_OutBuff[blockID] = uint4(shared_temp[GI].error, (shared_temp[GI].index_selector << 31) | shared_temp[GI].mode, + 0, shared_temp[GI].rotation); // rotation is indeed rotation for mode 4 5. for mode 6, rotation is p bit + } +} + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void TryMode137CS( uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID ) // mode 1 3 7 all have 2 subsets per block +{ + const uint MAX_USED_THREAD = 64; + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; + uint blockInGroup = GI / MAX_USED_THREAD; + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; + uint threadBase = blockInGroup * MAX_USED_THREAD; + uint threadInBlock = GI - threadBase; + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + if (threadInBlock < 16) + { + shared_temp[GI].pixel = clamp(uint4(g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ) * 255), 0, 255); + } + GroupMemoryBarrierWithGroupSync(); + + shared_temp[GI].error = 0xFFFFFFFF; + + uint4 pixel_r; + uint2x4 endPoint[2]; // endPoint[0..1 for subset id][0..1 for low and high in the subset] + uint2x4 endPointBackup[2]; + uint color_index; + if (threadInBlock < 64) + { + uint partition = threadInBlock; + + endPoint[0][0] = MAX_UINT; + endPoint[0][1] = MIN_UINT; + endPoint[1][0] = MAX_UINT; + endPoint[1][1] = MIN_UINT; + uint bits = candidateSectionBit[partition]; + for ( uint i = 0; i < 16; i ++ ) + { + uint4 pixel = shared_temp[threadBase + i].pixel; + if ( (( bits >> i ) & 0x01) == 1 ) + { + endPoint[1][0] = min( endPoint[1][0], pixel ); + endPoint[1][1] = max( endPoint[1][1], pixel ); + } + else + { + endPoint[0][0] = min( endPoint[0][0], pixel ); + endPoint[0][1] = max( endPoint[0][1], pixel ); + } + } + + endPointBackup[0] = endPoint[0]; + endPointBackup[1] = endPoint[1]; + + uint max_p; + if (1 == g_mode_id) + { + // in mode 1, there is only one p bit per subset + max_p = 4; + } + else + { + // in mode 3 7, there are two p bits per subset, one for each end point + max_p = 16; + } + + uint rotation = 0; + uint error = MAX_UINT; + for ( uint p = 0; p < max_p; p ++ ) + { + endPoint[0] = endPointBackup[0]; + endPoint[1] = endPointBackup[1]; + + for ( i = 0; i < 2; i ++ ) // loop through 2 subsets + { + if (g_mode_id == 1) + { + compress_endpoints1( endPoint[i], (p >> i) & 1 ); + } + else if (g_mode_id == 3) + { + compress_endpoints3( endPoint[i], uint2(p >> (i * 2 + 0), p >> (i * 2 + 1)) & 1 ); + } + else if (g_mode_id == 7) + { + compress_endpoints7( endPoint[i], uint2(p >> (i * 2 + 0), p >> (i * 2 + 1)) & 1 ); + } + } + + int4 span[2]; + span[0] = endPoint[0][1] - endPoint[0][0]; + span[1] = endPoint[1][1] - endPoint[1][0]; + + if (g_mode_id != 7) + { + span[0].w = span[1].w = 0; + } + + int span_norm_sqr[2]; + span_norm_sqr[0] = dot( span[0], span[0] ); + span_norm_sqr[1] = dot( span[1], span[1] ); + + // TODO: again, this shouldn't be necessary here in error calculation + int dotProduct = dot( span[0], shared_temp[threadBase + 0].pixel - endPoint[0][0] ); + if ( span_norm_sqr[0] > 0 && dotProduct > 0 && uint( dotProduct * 63.49999 ) > uint( 32 * span_norm_sqr[0] ) ) + { + span[0] = -span[0]; + swap(endPoint[0][0], endPoint[0][1]); + } + dotProduct = dot( span[1], shared_temp[threadBase + candidateFixUpIndex1D[partition].x].pixel - endPoint[1][0] ); + if ( span_norm_sqr[1] > 0 && dotProduct > 0 && uint( dotProduct * 63.49999 ) > uint( 32 * span_norm_sqr[1] ) ) + { + span[1] = -span[1]; + swap(endPoint[1][0], endPoint[1][1]); + } + + uint step_selector; + if (g_mode_id != 1) + { + step_selector = 2; // mode 3 7 have 2 bit index + } + else + { + step_selector = 1; // mode 1 has 3 bit index + } + + uint p_error = 0; + for ( i = 0; i < 16; i ++ ) + { + if (((bits >> i) & 0x01) == 1) + { + dotProduct = dot( span[1], shared_temp[threadBase + i].pixel - endPoint[1][0] ); + color_index = (span_norm_sqr[1] <= 0 || dotProduct <= 0) ? 0 + : ((dotProduct < span_norm_sqr[1]) ? aStep[step_selector][uint(dotProduct * 63.49999 / span_norm_sqr[1])] : aStep[step_selector][63]); + } + else + { + dotProduct = dot( span[0], shared_temp[threadBase + i].pixel - endPoint[0][0] ); + color_index = (span_norm_sqr[0] <= 0 || dotProduct <= 0) ? 0 + : ((dotProduct < span_norm_sqr[0]) ? aStep[step_selector][uint(dotProduct * 63.49999 / span_norm_sqr[0])] : aStep[step_selector][63]); + } + + uint subset_index = (bits >> i) & 0x01; + + pixel_r = ((64 - aWeight[step_selector][color_index]) * endPoint[subset_index][0] + + aWeight[step_selector][color_index] * endPoint[subset_index][1] + 32) >> 6; + if (g_mode_id != 7) + { + pixel_r.a = 255; + } + + uint4 pixel = shared_temp[threadBase + i].pixel; + Ensure_A_Is_Larger( pixel_r, pixel ); + pixel_r -= pixel; + p_error += ComputeError(pixel_r, pixel_r); + } + + if (p_error < error) + { + error = p_error; + rotation = p; + } + } + + shared_temp[GI].error = error; + shared_temp[GI].mode = g_mode_id; + shared_temp[GI].partition = partition; + shared_temp[GI].rotation = rotation; // mode 1 3 7 don't have rotation, we use rotation for p bits + } + GroupMemoryBarrierWithGroupSync(); + + if (threadInBlock < 32) + { + if ( shared_temp[GI].error > shared_temp[GI + 32].error ) + { + shared_temp[GI].error = shared_temp[GI + 32].error; + shared_temp[GI].mode = shared_temp[GI + 32].mode; + shared_temp[GI].partition = shared_temp[GI + 32].partition; + shared_temp[GI].rotation = shared_temp[GI + 32].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif +if (threadInBlock < 16) + { + if ( shared_temp[GI].error > shared_temp[GI + 16].error ) + { + shared_temp[GI].error = shared_temp[GI + 16].error; + shared_temp[GI].mode = shared_temp[GI + 16].mode; + shared_temp[GI].partition = shared_temp[GI + 16].partition; + shared_temp[GI].rotation = shared_temp[GI + 16].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 8) + { + if ( shared_temp[GI].error > shared_temp[GI + 8].error ) + { + shared_temp[GI].error = shared_temp[GI + 8].error; + shared_temp[GI].mode = shared_temp[GI + 8].mode; + shared_temp[GI].partition = shared_temp[GI + 8].partition; + shared_temp[GI].rotation = shared_temp[GI + 8].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + if ( shared_temp[GI].error > shared_temp[GI + 4].error ) + { + shared_temp[GI].error = shared_temp[GI + 4].error; + shared_temp[GI].mode = shared_temp[GI + 4].mode; + shared_temp[GI].partition = shared_temp[GI + 4].partition; + shared_temp[GI].rotation = shared_temp[GI + 4].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + if ( shared_temp[GI].error > shared_temp[GI + 2].error ) + { + shared_temp[GI].error = shared_temp[GI + 2].error; + shared_temp[GI].mode = shared_temp[GI + 2].mode; + shared_temp[GI].partition = shared_temp[GI + 2].partition; + shared_temp[GI].rotation = shared_temp[GI + 2].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + if ( shared_temp[GI].error > shared_temp[GI + 1].error ) + { + shared_temp[GI].error = shared_temp[GI + 1].error; + shared_temp[GI].mode = shared_temp[GI + 1].mode; + shared_temp[GI].partition = shared_temp[GI + 1].partition; + shared_temp[GI].rotation = shared_temp[GI + 1].rotation; + } + + if (g_InBuff[blockID].x > shared_temp[GI].error) + { + g_OutBuff[blockID] = uint4(shared_temp[GI].error, shared_temp[GI].mode, shared_temp[GI].partition, shared_temp[GI].rotation); // mode 1 3 7 don't have rotation, we use rotation for p bits + } + else + { + g_OutBuff[blockID] = g_InBuff[blockID]; + } + } +} + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void TryMode02CS( uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID ) // mode 0 2 have 3 subsets per block +{ + const uint MAX_USED_THREAD = 64; + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; + uint blockInGroup = GI / MAX_USED_THREAD; + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; + uint threadBase = blockInGroup * MAX_USED_THREAD; + uint threadInBlock = GI - threadBase; + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + if (threadInBlock < 16) + { + shared_temp[GI].pixel = clamp(uint4(g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ) * 255), 0, 255); + } + GroupMemoryBarrierWithGroupSync(); + + shared_temp[GI].error = 0xFFFFFFFF; + + uint num_partitions; + if (0 == g_mode_id) + { + num_partitions = 16; + } + else + { + num_partitions = 64; + } + + uint4 pixel_r; + uint2x4 endPoint[3]; // endPoint[0..1 for subset id][0..1 for low and high in the subset] + uint2x4 endPointBackup[3]; + uint color_index[16]; + if (threadInBlock < num_partitions) + { + uint partition = threadInBlock + 64; + + endPoint[0][0] = MAX_UINT; + endPoint[0][1] = MIN_UINT; + endPoint[1][0] = MAX_UINT; + endPoint[1][1] = MIN_UINT; + endPoint[2][0] = MAX_UINT; + endPoint[2][1] = MIN_UINT; + uint bits2 = candidateSectionBit2[partition - 64]; + for ( uint i = 0; i < 16; i ++ ) + { + uint4 pixel = shared_temp[threadBase + i].pixel; + uint subset_index = ( bits2 >> ( i * 2 ) ) & 0x03; + if ( subset_index == 2 ) + { + endPoint[2][0] = min( endPoint[2][0], pixel ); + endPoint[2][1] = max( endPoint[2][1], pixel ); + } + else if ( subset_index == 1 ) + { + endPoint[1][0] = min( endPoint[1][0], pixel ); + endPoint[1][1] = max( endPoint[1][1], pixel ); + } + else + { + endPoint[0][0] = min( endPoint[0][0], pixel ); + endPoint[0][1] = max( endPoint[0][1], pixel ); + } + } + + endPointBackup[0] = endPoint[0]; + endPointBackup[1] = endPoint[1]; + endPointBackup[2] = endPoint[2]; + + uint max_p; + if (0 == g_mode_id) + { + max_p = 64; // changed from 32 to 64 + } + else + { + max_p = 1; + } + + uint rotation = 0; + uint error = MAX_UINT; + for ( uint p = 0; p < max_p; p ++ ) + { + endPoint[0] = endPointBackup[0]; + endPoint[1] = endPointBackup[1]; + endPoint[2] = endPointBackup[2]; + + for ( i = 0; i < 3; i ++ ) + { + if (0 == g_mode_id) + { + compress_endpoints0( endPoint[i], uint2(p >> (i * 2 + 0), p >> (i * 2 + 1)) & 1 ); + } + else + { + compress_endpoints2( endPoint[i] ); + } + } + + uint step_selector = 1 + (2 == g_mode_id); + + int4 span[3]; + span[0] = endPoint[0][1] - endPoint[0][0]; + span[1] = endPoint[1][1] - endPoint[1][0]; + span[2] = endPoint[2][1] - endPoint[2][0]; + span[0].w = span[1].w = span[2].w = 0; + int span_norm_sqr[3]; + span_norm_sqr[0] = dot( span[0], span[0] ); + span_norm_sqr[1] = dot( span[1], span[1] ); + span_norm_sqr[2] = dot( span[2], span[2] ); + + // TODO: again, this shouldn't be necessary here in error calculation + uint ci[3] = { 0, candidateFixUpIndex1D[partition].x, candidateFixUpIndex1D[partition].y }; + for (i = 0; i < 3; i ++) + { + int dotProduct = dot( span[i], shared_temp[threadBase + ci[i]].pixel - endPoint[i][0] ); + if ( span_norm_sqr[i] > 0 && dotProduct > 0 && uint( dotProduct * 63.49999 ) > uint( 32 * span_norm_sqr[i] ) ) + { + span[i] = -span[i]; + swap(endPoint[i][0], endPoint[i][1]); + } + } + + uint p_error = 0; + for ( i = 0; i < 16; i ++ ) + { + uint subset_index = ( bits2 >> ( i * 2 ) ) & 0x03; + if ( subset_index == 2 ) + { + int dotProduct = dot( span[2], shared_temp[threadBase + i].pixel - endPoint[2][0] ); + color_index[i] = ( span_norm_sqr[2] <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr[2] ) ? aStep[step_selector][ uint( dotProduct * 63.49999 / span_norm_sqr[2] ) ] : aStep[step_selector][63] ); + } + else if ( subset_index == 1 ) + { + int dotProduct = dot( span[1], shared_temp[threadBase + i].pixel - endPoint[1][0] ); + color_index[i] = ( span_norm_sqr[1] <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr[1] ) ? aStep[step_selector][ uint( dotProduct * 63.49999 / span_norm_sqr[1] ) ] : aStep[step_selector][63] ); + } + else + { + int dotProduct = dot( span[0], shared_temp[threadBase + i].pixel - endPoint[0][0] ); + color_index[i] = ( span_norm_sqr[0] <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr[0] ) ? aStep[step_selector][ uint( dotProduct * 63.49999 / span_norm_sqr[0] ) ] : aStep[step_selector][63] ); + } + + pixel_r = ( ( 64 - aWeight[step_selector][color_index[i]] ) * endPoint[subset_index][0] + + aWeight[step_selector][color_index[i]] * endPoint[subset_index][1] + 32 ) >> 6; + pixel_r.a = 255; + + uint4 pixel = shared_temp[threadBase + i].pixel; + Ensure_A_Is_Larger( pixel_r, pixel ); + pixel_r -= pixel; + p_error += ComputeError(pixel_r, pixel_r); + } + + if (p_error < error) + { + error = p_error; + rotation = p; // Borrow rotation for p + } + } + + shared_temp[GI].error = error; + shared_temp[GI].partition = partition; + shared_temp[GI].rotation = rotation; + } + GroupMemoryBarrierWithGroupSync(); + + if (threadInBlock < 32) + { + if ( shared_temp[GI].error > shared_temp[GI + 32].error ) + { + shared_temp[GI].error = shared_temp[GI + 32].error; + shared_temp[GI].partition = shared_temp[GI + 32].partition; + shared_temp[GI].rotation = shared_temp[GI + 32].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 16) + { + if ( shared_temp[GI].error > shared_temp[GI + 16].error ) + { + shared_temp[GI].error = shared_temp[GI + 16].error; + shared_temp[GI].partition = shared_temp[GI + 16].partition; + shared_temp[GI].rotation = shared_temp[GI + 16].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 8) + { + if ( shared_temp[GI].error > shared_temp[GI + 8].error ) + { + shared_temp[GI].error = shared_temp[GI + 8].error; + shared_temp[GI].partition = shared_temp[GI + 8].partition; + shared_temp[GI].rotation = shared_temp[GI + 8].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + if ( shared_temp[GI].error > shared_temp[GI + 4].error ) + { + shared_temp[GI].error = shared_temp[GI + 4].error; + shared_temp[GI].partition = shared_temp[GI + 4].partition; + shared_temp[GI].rotation = shared_temp[GI + 4].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + if ( shared_temp[GI].error > shared_temp[GI + 2].error ) + { + shared_temp[GI].error = shared_temp[GI + 2].error; + shared_temp[GI].partition = shared_temp[GI + 2].partition; + shared_temp[GI].rotation = shared_temp[GI + 2].rotation; + } + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + if ( shared_temp[GI].error > shared_temp[GI + 1].error ) + { + shared_temp[GI].error = shared_temp[GI + 1].error; + shared_temp[GI].partition = shared_temp[GI + 1].partition; + shared_temp[GI].rotation = shared_temp[GI + 1].rotation; + } + + if (g_InBuff[blockID].x > shared_temp[GI].error) + { + g_OutBuff[blockID] = uint4(shared_temp[GI].error, g_mode_id, shared_temp[GI].partition, shared_temp[GI].rotation); // rotation is actually p bit for mode 0. for mode 2, rotation is always 0 + } + else + { + g_OutBuff[blockID] = g_InBuff[blockID]; + } + } +} + +[numthreads( THREAD_GROUP_SIZE, 1, 1 )] +void EncodeBlockCS(uint GI : SV_GroupIndex, uint3 groupID : SV_GroupID) +{ + const uint MAX_USED_THREAD = 16; + uint BLOCK_IN_GROUP = THREAD_GROUP_SIZE / MAX_USED_THREAD; + uint blockInGroup = GI / MAX_USED_THREAD; + uint blockID = g_start_block_id + groupID.x * BLOCK_IN_GROUP + blockInGroup; + uint threadBase = blockInGroup * MAX_USED_THREAD; + uint threadInBlock = GI - threadBase; + +#ifndef REF_DEVICE + if (blockID >= g_num_total_blocks) + { + return; + } +#endif + + uint block_y = blockID / g_num_block_x; + uint block_x = blockID - block_y * g_num_block_x; + uint base_x = block_x * BLOCK_SIZE_X; + uint base_y = block_y * BLOCK_SIZE_Y; + + uint mode = g_InBuff[blockID].y & 0x7FFFFFFF; + uint partition = g_InBuff[blockID].z; + uint index_selector = (g_InBuff[blockID].y >> 31) & 1; + uint rotation = g_InBuff[blockID].w; + + if (threadInBlock < 16) + { + uint4 pixel = clamp(uint4(g_Input.Load( uint3( base_x + threadInBlock % 4, base_y + threadInBlock / 4, 0 ) ) * 255), 0, 255); + + if ((4 == mode) || (5 == mode)) + { + if (1 == rotation) + { + pixel.ra = pixel.ar; + } + else if (2 == rotation) + { + pixel.ga = pixel.ag; + } + else if (3 == rotation) + { + pixel.ba = pixel.ab; + } + } + + shared_temp[GI].pixel = pixel; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + uint bits = candidateSectionBit[partition]; + uint bits2 = candidateSectionBit2[partition - 64]; + + uint2x4 ep; + uint2x4 ep_quantized; + [unroll] + for (int ii = 2; ii >= 0; -- ii) + { + if (threadInBlock < 16) + { + uint2x4 ep; + ep[0] = MAX_UINT; + ep[1] = MIN_UINT; + + uint4 pixel = shared_temp[GI].pixel; + + uint subset_index = ( bits >> threadInBlock ) & 0x01; + uint subset_index2 = ( bits2 >> ( threadInBlock * 2 ) ) & 0x03; + if (0 == ii) + { + if ((0 == mode) || (2 == mode)) + { + if (0 == subset_index2) + { + ep[0] = ep[1] = pixel; + } + } + else if ((1 == mode) || (3 == mode) || (7 == mode)) + { + if (0 == subset_index) + { + ep[0] = ep[1] = pixel; + } + } + else if ((4 == mode) || (5 == mode) || (6 == mode)) + { + ep[0] = ep[1] = pixel; + } + } + else if (1 == ii) + { + if ((0 == mode) || (2 == mode)) + { + if (1 == subset_index2) + { + ep[0] = ep[1] = pixel; + } + } + else if ((1 == mode) || (3 == mode) || (7 == mode)) + { + if (1 == subset_index) + { + ep[0] = ep[1] = pixel; + } + } + } + else + { + if ((0 == mode) || (2 == mode)) + { + if (2 == subset_index2) + { + ep[0] = ep[1] = pixel; + } + } + } + + shared_temp[GI].endPoint_low = ep[0]; + shared_temp[GI].endPoint_high = ep[1]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 8) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 8].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 8].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 4) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 4].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 4].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 2) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 2].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 2].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + if (threadInBlock < 1) + { + shared_temp[GI].endPoint_low = min(shared_temp[GI].endPoint_low, shared_temp[GI + 1].endPoint_low); + shared_temp[GI].endPoint_high = max(shared_temp[GI].endPoint_high, shared_temp[GI + 1].endPoint_high); + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (ii == (int)threadInBlock) + { + ep[0] = shared_temp[threadBase].endPoint_low; + ep[1] = shared_temp[threadBase].endPoint_high; + } + } + + if (threadInBlock < 3) + { + uint2 P; + if (1 == mode) + { + P = (rotation >> threadInBlock) & 1; + } + else + { + P = uint2(rotation >> (threadInBlock * 2 + 0), rotation >> (threadInBlock * 2 + 1)) & 1; + } + + if (0 == mode) + { + ep_quantized = compress_endpoints0( ep, P ); + } + else if (1 == mode) + { + ep_quantized = compress_endpoints1( ep, P ); + } + else if (2 == mode) + { + ep_quantized = compress_endpoints2( ep ); + } + else if (3 == mode) + { + ep_quantized = compress_endpoints3( ep, P ); + } + else if (4 == mode) + { + ep_quantized = compress_endpoints4( ep ); + } + else if (5 == mode) + { + ep_quantized = compress_endpoints5( ep ); + } + else if (6 == mode) + { + ep_quantized = compress_endpoints6( ep, P ); + } + else //if (7 == mode) + { + ep_quantized = compress_endpoints7( ep, P ); + } + + int4 span = ep[1] - ep[0]; + if (mode < 4) + { + span.w = 0; + } + + if ((4 == mode) || (5 == mode)) + { + if (0 == threadInBlock) + { + int2 span_norm_sqr = uint2( dot( span.rgb, span.rgb ), span.a * span.a ); + int2 dotProduct = int2( dot( span.rgb, shared_temp[threadBase + 0].pixel.rgb - ep[0].rgb ), span.a * ( shared_temp[threadBase + 0].pixel.a - ep[0].a ) ); + if ( span_norm_sqr.x > 0 && dotProduct.x > 0 && uint( dotProduct.x * 63.49999 ) > uint( 32 * span_norm_sqr.x ) ) + { + swap(ep[0].rgb, ep[1].rgb); + swap(ep_quantized[0].rgb, ep_quantized[1].rgb); + } + if ( span_norm_sqr.y > 0 && dotProduct.y > 0 && uint( dotProduct.y * 63.49999 ) > uint( 32 * span_norm_sqr.y ) ) + { + swap(ep[0].a, ep[1].a); + swap(ep_quantized[0].a, ep_quantized[1].a); + } + } + } + else //if ((0 == mode) || (2 == mode) || (1 == mode) || (3 == mode) || (7 == mode) || (6 == mode)) + { + int p; + if (0 == threadInBlock) + { + p = 0; + } + else if (1 == threadInBlock) + { + p = candidateFixUpIndex1D[partition].x; + } + else //if (2 == threadInBlock) + { + p = candidateFixUpIndex1D[partition].y; + } + + int span_norm_sqr = dot( span, span ); + int dotProduct = dot( span, shared_temp[threadBase + p].pixel - ep[0] ); + if ( span_norm_sqr > 0 && dotProduct > 0 && uint( dotProduct * 63.49999 ) > uint( 32 * span_norm_sqr ) ) + { + swap(ep[0], ep[1]); + swap(ep_quantized[0], ep_quantized[1]); + } + } + + shared_temp[GI].endPoint_low = ep[0]; + shared_temp[GI].endPoint_high = ep[1]; + shared_temp[GI].endPoint_low_quantized = ep_quantized[0]; + shared_temp[GI].endPoint_high_quantized = ep_quantized[1]; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (threadInBlock < 16) + { + uint color_index = 0; + uint alpha_index = 0; + + uint2x4 ep; + + uint2 indexPrec; + if ((0 == mode) || (1 == mode)) + { + indexPrec = 1; + } + else if (6 == mode) + { + indexPrec = 0; + } + else if (4 == mode) + { + if (0 == index_selector) + { + indexPrec = uint2(2, 1); + } + else + { + indexPrec = uint2(1, 2); + } + } + else + { + indexPrec = 2; + } + + int subset_index; + if ((0 == mode) || (2 == mode)) + { + subset_index = (bits2 >> (threadInBlock * 2)) & 0x03; + } + else if ((1 == mode) || (3 == mode) || (7 == mode)) + { + subset_index = (bits >> threadInBlock) & 0x01; + } + else + { + subset_index = 0; + } + + ep[0] = shared_temp[threadBase + subset_index].endPoint_low; + ep[1] = shared_temp[threadBase + subset_index].endPoint_high; + + int4 span = ep[1] - ep[0]; + if (mode < 4) + { + span.w = 0; + } + + if ((4 == mode) || (5 == mode)) + { + int2 span_norm_sqr; + span_norm_sqr.x = dot( span.rgb, span.rgb ); + span_norm_sqr.y = span.a * span.a; + + int dotProduct = dot( span.rgb, shared_temp[threadBase + threadInBlock].pixel.rgb - ep[0].rgb ); + color_index = ( span_norm_sqr.x <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr.x ) ? aStep[indexPrec.x][ uint( dotProduct * 63.49999 / span_norm_sqr.x ) ] : aStep[indexPrec.x][63] ); + dotProduct = dot( span.a, shared_temp[threadBase + threadInBlock].pixel.a - ep[0].a ); + alpha_index = ( span_norm_sqr.y <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr.y ) ? aStep[indexPrec.y][ uint( dotProduct * 63.49999 / span_norm_sqr.y ) ] : aStep[indexPrec.y][63] ); + + if (index_selector) + { + swap(color_index, alpha_index); + } + } + else + { + int span_norm_sqr = dot( span, span ); + + int dotProduct = dot( span, shared_temp[threadBase + threadInBlock].pixel - ep[0] ); + color_index = ( span_norm_sqr <= 0 || dotProduct <= 0 ) ? 0 + : ( ( dotProduct < span_norm_sqr ) ? aStep[indexPrec.x][ uint( dotProduct * 63.49999 / span_norm_sqr ) ] : aStep[indexPrec.x][63] ); + } + + shared_temp[GI].error = color_index; + shared_temp[GI].mode = alpha_index; + } +#ifdef REF_DEVICE + GroupMemoryBarrierWithGroupSync(); +#endif + + if (0 == threadInBlock) + { + uint4 block; + if (0 == mode) + { + block_package0( block, partition, threadBase ); + } + else if (1 == mode) + { + block_package1( block, partition, threadBase ); + } + else if (2 == mode) + { + block_package2( block, partition, threadBase ); + } + else if (3 == mode) + { + block_package3( block, partition, threadBase ); + } + else if (4 == mode) + { + block_package4( block, rotation, index_selector, threadBase ); + } + else if (5 == mode) + { + block_package5( block, rotation, threadBase ); + } + else if (6 == mode) + { + block_package6( block, threadBase ); + } + else //if (7 == mode) + { + block_package7( block, partition, threadBase ); + } + + g_OutBuff[blockID] = block; + } +} + +//uint4 truncate_and_round( uint4 color, uint bits) +//{ +// uint precisionMask = ((1 << bits) - 1) << (8 - bits); +// uint precisionHalf = (1 << (7-bits)); +// +// uint4 truncated = color & precisionMask; +// uint4 rounded = min(255, color + precisionHalf) & precisionMask; +// +// uint4 truncated_bak = truncated = truncated | (truncated >> bits); +// uint4 rounded_bak = rounded = rounded | (rounded >> bits); +// +// uint4 color_bak = color; +// +// Ensure_A_Is_Larger( rounded, color ); +// Ensure_A_Is_Larger( truncated, color_bak ); +// +// if (dot(rounded - color, rounded - color) < +// dot(truncated - color_bak, truncated - color_bak)) +// { +// return rounded_bak; +// } +// else +// { +// return truncated_bak; +// } +//} + +uint4 quantize( uint4 color, uint uPrec ) +{ + uint4 rnd = min(255, color + (1 << (7 - uPrec))); + return rnd >> (8 - uPrec); +} + +uint4 unquantize( uint4 color, uint uPrec ) +{ + color = color << (8 - uPrec); + return color | (color >> uPrec); +} + +uint2x4 compress_endpoints0( inout uint2x4 endPoint, uint2 P ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j].rgb = quantize(endPoint[j].rgbb, 5).rgb & 0xFFFFFFFE; + quantized[j].rgb |= P[j]; + quantized[j].a = 0xFF; + + endPoint[j].rgb = unquantize(quantized[j].rgbb, 5).rgb; + endPoint[j].a = 0xFF; + + quantized[j] <<= 3; + } + return quantized; +} +uint2x4 compress_endpoints1( inout uint2x4 endPoint, uint2 P ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j].rgb = quantize(endPoint[j].rgbb, 7).rgb & 0xFFFFFFFE; + quantized[j].rgb |= P[j]; + quantized[j].a = 0xFF; + + endPoint[j].rgb = unquantize(quantized[j].rgbb, 7).rgb; + endPoint[j].a = 0xFF; + + quantized[j] <<= 1; + } + return quantized; +} +uint2x4 compress_endpoints2( inout uint2x4 endPoint ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j].rgb = quantize(endPoint[j].rgbb, 5).rgb; + quantized[j].a = 0xFF; + + endPoint[j].rgb = unquantize(quantized[j].rgbb, 5).rgb; + endPoint[j].a = 0xFF; + + quantized[j] <<= 3; + } + return quantized; +} +uint2x4 compress_endpoints3( inout uint2x4 endPoint, uint2 P ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j].rgb = endPoint[j].rgb & 0xFFFFFFFE; + quantized[j].rgb |= P[j]; + quantized[j].a = 0xFF; + + endPoint[j].rgb = quantized[j].rgb; + endPoint[j].a = 0xFF; + } + return quantized; +} +uint2x4 compress_endpoints4( inout uint2x4 endPoint ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j].rgb = quantize(endPoint[j].rgbb, 5).rgb; + quantized[j].a = quantize(endPoint[j].a, 6).r; + + endPoint[j].rgb = unquantize(quantized[j].rgbb, 5).rgb; + endPoint[j].a = unquantize(quantized[j].a, 6).r; + + quantized[j].rgb <<= 3; + quantized[j].a <<= 2; + } + return quantized; +} +uint2x4 compress_endpoints5( inout uint2x4 endPoint ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j].rgb = quantize(endPoint[j].rgbb, 7).rgb; + quantized[j].a = endPoint[j].a; + + endPoint[j].rgb = unquantize(quantized[j].rgbb, 7).rgb; + // endPoint[j].a Alpha is full precision + + quantized[j].rgb <<= 1; + } + return quantized; +} +uint2x4 compress_endpoints6( inout uint2x4 endPoint, uint2 P ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j] = endPoint[j] & 0xFFFFFFFE; + quantized[j] |= P[j]; + + endPoint[j] = quantized[j]; + } + return quantized; +} +uint2x4 compress_endpoints7( inout uint2x4 endPoint, uint2 P ) +{ + uint2x4 quantized; + for ( uint j = 0; j < 2; j ++ ) + { + quantized[j] = quantize(endPoint[j], 6) & 0xFFFFFFFE; + quantized[j] |= P[j]; + + endPoint[j] = unquantize(quantized[j], 6); + } + return quantized << 2; +} + +#define get_end_point_l(subset) shared_temp[threadBase + subset].endPoint_low_quantized +#define get_end_point_h(subset) shared_temp[threadBase + subset].endPoint_high_quantized +#define get_color_index(index) shared_temp[threadBase + index].error +#define get_alpha_index(index) shared_temp[threadBase + index].mode + +void block_package0( out uint4 block, uint partition, uint threadBase ) +{ + block.x = 0x01 | ( (partition - 64) << 1 ) + | ( ( get_end_point_l(0).r & 0xF0 ) << 1 ) | ( ( get_end_point_h(0).r & 0xF0 ) << 5 ) + | ( ( get_end_point_l(1).r & 0xF0 ) << 9 ) | ( ( get_end_point_h(1).r & 0xF0 ) << 13 ) + | ( ( get_end_point_l(2).r & 0xF0 ) << 17 ) | ( ( get_end_point_h(2).r & 0xF0 ) << 21 ) + | ( ( get_end_point_l(0).g & 0xF0 ) << 25 ); + block.y = ( ( get_end_point_l(0).g & 0xF0 ) >> 7 ) | ( ( get_end_point_h(0).g & 0xF0 ) >> 3 ) + | ( ( get_end_point_l(1).g & 0xF0 ) << 1 ) | ( ( get_end_point_h(1).g & 0xF0 ) << 5 ) + | ( ( get_end_point_l(2).g & 0xF0 ) << 9 ) | ( ( get_end_point_h(2).g & 0xF0 ) << 13 ) + | ( ( get_end_point_l(0).b & 0xF0 ) << 17 ) | ( ( get_end_point_h(0).b & 0xF0 ) << 21 ) + | ( ( get_end_point_l(1).b & 0xF0 ) << 25 ); + block.z = ( ( get_end_point_l(1).b & 0xF0 ) >> 7 ) | ( ( get_end_point_h(1).b & 0xF0 ) >> 3 ) + | ( ( get_end_point_l(2).b & 0xF0 ) << 1 ) | ( ( get_end_point_h(2).b & 0xF0 ) << 5 ) + | ( ( get_end_point_l(0).r & 0x08 ) << 10 ) | ( ( get_end_point_h(0).r & 0x08 ) << 11 ) + | ( ( get_end_point_l(1).r & 0x08 ) << 12 ) | ( ( get_end_point_h(1).r & 0x08 ) << 13 ) + | ( ( get_end_point_l(2).r & 0x08 ) << 14 ) | ( ( get_end_point_h(2).r & 0x08 ) << 15 ) + | ( get_color_index(0) << 19 ); + block.w = 0; + uint i = 1; + for ( ; i <= min( candidateFixUpIndex1DOrdered[partition][0], 4 ); i ++ ) + { + block.z |= get_color_index(i) << ( i * 3 + 18 ); + } + if ( candidateFixUpIndex1DOrdered[partition][0] < 4 ) //i = 4 + { + block.z |= get_color_index(4) << 29; + i += 1; + } + else //i = 5 + { + block.w |= ( get_color_index(4) & 0x04 ) >> 2; + for ( ; i <= candidateFixUpIndex1DOrdered[partition][0]; i ++ ) + block.w |= get_color_index(i) << ( i * 3 - 14 ); + } + for ( ; i <= candidateFixUpIndex1DOrdered[partition][1]; i ++ ) + { + block.w |= get_color_index(i) << ( i * 3 - 15 ); + } + for ( ; i < 16; i ++ ) + { + block.w |= get_color_index(i) << ( i * 3 - 16 ); + } +} +void block_package1( out uint4 block, uint partition, uint threadBase ) +{ + block.x = 0x02 | ( partition << 2 ) + | ( ( get_end_point_l(0).r & 0xFC ) << 6 ) | ( ( get_end_point_h(0).r & 0xFC ) << 12 ) + | ( ( get_end_point_l(1).r & 0xFC ) << 18 ) | ( ( get_end_point_h(1).r & 0xFC ) << 24 ); + block.y = ( ( get_end_point_l(0).g & 0xFC ) >> 2 ) | ( ( get_end_point_h(0).g & 0xFC ) << 4 ) + | ( ( get_end_point_l(1).g & 0xFC ) << 10 ) | ( ( get_end_point_h(1).g & 0xFC ) << 16 ) + | ( ( get_end_point_l(0).b & 0xFC ) << 22 ) | ( ( get_end_point_h(0).b & 0xFC ) << 28 ); + block.z = ( ( get_end_point_h(0).b & 0xFC ) >> 4 ) | ( ( get_end_point_l(1).b & 0xFC ) << 2 ) + | ( ( get_end_point_h(1).b & 0xFC ) << 8 ) + | ( ( get_end_point_l(0).r & 0x02 ) << 15 ) | ( ( get_end_point_l(1).r & 0x02 ) << 16 ) + | ( get_color_index(0) << 18 ); + if ( candidateFixUpIndex1DOrdered[partition][0] == 15 ) + { + block.w = (get_color_index(15) << 30) | (get_color_index(14) << 27) | (get_color_index(13) << 24) | (get_color_index(12) << 21) | (get_color_index(11) << 18) | (get_color_index(10) << 15) + | (get_color_index(9) << 12) | (get_color_index(8) << 9) | (get_color_index(7) << 6) | (get_color_index(6) << 3) | get_color_index(5); + block.z |= (get_color_index(4) << 29) | (get_color_index(3) << 26) | (get_color_index(2) << 23) | (get_color_index(1) << 20) | (get_color_index(0) << 18); + } + else if ( candidateFixUpIndex1DOrdered[partition][0] == 2 ) + { + block.w = (get_color_index(15) << 29) | (get_color_index(14) << 26) | (get_color_index(13) << 23) | (get_color_index(12) << 20) | (get_color_index(11) << 17) | (get_color_index(10) << 14) + | (get_color_index(9) << 11) | (get_color_index(8) << 8) | (get_color_index(7) << 5) | (get_color_index(6) << 2) | (get_color_index(5) >> 1); + block.z |= (get_color_index(5) << 31) | (get_color_index(4) << 28) | (get_color_index(3) << 25) | (get_color_index(2) << 23) | (get_color_index(1) << 20) | (get_color_index(0) << 18); + } + else if ( candidateFixUpIndex1DOrdered[partition][0] == 8 ) + { + block.w = (get_color_index(15) << 29) | (get_color_index(14) << 26) | (get_color_index(13) << 23) | (get_color_index(12) << 20) | (get_color_index(11) << 17) | (get_color_index(10) << 14) + | (get_color_index(9) << 11) | (get_color_index(8) << 9) | (get_color_index(7) << 6) | (get_color_index(6) << 3) | get_color_index(5); + block.z |= (get_color_index(4) << 29) | (get_color_index(3) << 26) | (get_color_index(2) << 23) | (get_color_index(1) << 20) | (get_color_index(0) << 18); + } + else //candidateFixUpIndex1DOrdered[partition] == 6 + { + block.w = (get_color_index(15) << 29) | (get_color_index(14) << 26) | (get_color_index(13) << 23) | (get_color_index(12) << 20) | (get_color_index(11) << 17) | (get_color_index(10) << 14) + | (get_color_index(9) << 11) | (get_color_index(8) << 8) | (get_color_index(7) << 6) | (get_color_index(6) << 4) | get_color_index(5); + block.z |= (get_color_index(4) << 29) | (get_color_index(3) << 26) | (get_color_index(2) << 23) | (get_color_index(1) << 20) | (get_color_index(0) << 18); + } +} +void block_package2( out uint4 block, uint partition, uint threadBase ) +{ + block.x = 0x04 | ( (partition - 64) << 3 ) + | ( ( get_end_point_l(0).r & 0xF8 ) << 6 ) | ( ( get_end_point_h(0).r & 0xF8 ) << 11 ) + | ( ( get_end_point_l(1).r & 0xF8 ) << 16 ) | ( ( get_end_point_h(1).r & 0xF8 ) << 21 ) + | ( ( get_end_point_l(2).r & 0xF8 ) << 26 ); + block.y = ( ( get_end_point_l(2).r & 0xF8 ) >> 6 ) | ( ( get_end_point_h(2).r & 0xF8 ) >> 1 ) + | ( ( get_end_point_l(0).g & 0xF8 ) << 4 ) | ( ( get_end_point_h(0).g & 0xF8 ) << 9 ) + | ( ( get_end_point_l(1).g & 0xF8 ) << 14 ) | ( ( get_end_point_h(1).g & 0xF8 ) << 19 ) + | ( ( get_end_point_l(2).g & 0xF8 ) << 24 ); + block.z = ( ( get_end_point_h(2).g & 0xF8 ) >> 3 ) | ( ( get_end_point_l(0).b & 0xF8 ) << 2 ) + | ( ( get_end_point_h(0).b & 0xF8 ) << 7 ) | ( ( get_end_point_l(1).b & 0xF8 ) << 12 ) + | ( ( get_end_point_h(1).b & 0xF8 ) << 17 ) | ( ( get_end_point_l(2).b & 0xF8 ) << 22 ) + | ( ( get_end_point_h(2).b & 0xF8 ) << 27 ); + block.w = ( ( get_end_point_h(2).b & 0xF8 ) >> 5 ) + | ( get_color_index(0) << 3 ); + uint i = 1; + for ( ; i <= candidateFixUpIndex1DOrdered[partition][0]; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 + 2 ); + } + for ( ; i <= candidateFixUpIndex1DOrdered[partition][1]; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 + 1 ); + } + for ( ; i < 16; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 ); + } +} +void block_package3( out uint4 block, uint partition, uint threadBase ) +{ + block.x = 0x08 | ( partition << 4 ) + | ( ( get_end_point_l(0).r & 0xFE ) << 9 ) | ( ( get_end_point_h(0).r & 0xFE ) << 16 ) + | ( ( get_end_point_l(1).r & 0xFE ) << 23 ) | ( ( get_end_point_h(1).r & 0xFE ) << 30 ); + block.y = ( ( get_end_point_h(1).r & 0xFE ) >> 2 ) | ( ( get_end_point_l(0).g & 0xFE ) << 5 ) + | ( ( get_end_point_h(0).g & 0xFE ) << 12 ) | ( ( get_end_point_l(1).g & 0xFE ) << 19 ) + | ( ( get_end_point_h(1).g & 0xFE ) << 26 ); + block.z = ( ( get_end_point_h(1).g & 0xFE ) >> 6 ) | ( ( get_end_point_l(0).b & 0xFE ) << 1 ) + | ( ( get_end_point_h(0).b & 0xFE ) << 8 ) | ( ( get_end_point_l(1).b & 0xFE ) << 15 ) + | ( ( get_end_point_h(1).b & 0xFE ) << 22 ) + | ( ( get_end_point_l(0).r & 0x01 ) << 30 ) | ( ( get_end_point_h(0).r & 0x01 ) << 31 ); + block.w = ( ( get_end_point_l(1).r & 0x01 ) << 0 ) | ( ( get_end_point_h(1).r & 0x01 ) << 1 ) + | ( get_color_index(0) << 2 ); + uint i = 1; + for ( ; i <= candidateFixUpIndex1DOrdered[partition][0]; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 + 1 ); + } + for ( ; i < 16; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 ); + } +} +void block_package4( out uint4 block, uint rotation, uint index_selector, uint threadBase ) +{ + block.x = 0x10 | ( (rotation & 3) << 5 ) | ( (index_selector & 1) << 7 ) + | ( ( get_end_point_l(0).r & 0xF8 ) << 5 ) | ( ( get_end_point_h(0).r & 0xF8 ) << 10 ) + | ( ( get_end_point_l(0).g & 0xF8 ) << 15 ) | ( ( get_end_point_h(0).g & 0xF8 ) << 20 ) + | ( ( get_end_point_l(0).b & 0xF8 ) << 25 ); + + block.y = ( ( get_end_point_l(0).b & 0xF8 ) >> 7 ) | ( ( get_end_point_h(0).b & 0xF8 ) >> 2 ) + | ( ( get_end_point_l(0).a & 0xFC ) << 4 ) | ( ( get_end_point_h(0).a & 0xFC ) << 10 ) + | ( (get_color_index(0) & 1) << 18 ) | ( get_color_index(1) << 19 ) | ( get_color_index(2) << 21 ) | ( get_color_index(3) << 23 ) + | ( get_color_index(4) << 25 ) | ( get_color_index(5) << 27 ) | ( get_color_index(6) << 29 ) | ( get_color_index(7) << 31 ); + + block.z = ( get_color_index(7) >> 1 ) | ( get_color_index(8) << 1 ) | ( get_color_index(9) << 3 ) | ( get_color_index(10)<< 5 ) + | ( get_color_index(11)<< 7 ) | ( get_color_index(12)<< 9 ) | ( get_color_index(13)<< 11 ) | ( get_color_index(14)<< 13 ) + | ( get_color_index(15)<< 15 ) | ( (get_alpha_index(0) & 3) << 17 ) | ( get_alpha_index(1) << 19 ) | ( get_alpha_index(2) << 22 ) + | ( get_alpha_index(3) << 25 ) | ( get_alpha_index(4) << 28 ) | ( get_alpha_index(5) << 31 ); + + block.w = ( get_alpha_index(5) >> 1 ) | ( get_alpha_index(6) << 2 ) | ( get_alpha_index(7) << 5 ) | ( get_alpha_index(8) << 8 ) + | ( get_alpha_index(9) << 11 ) | ( get_alpha_index(10)<< 14 ) | ( get_alpha_index(11)<< 17 ) | ( get_alpha_index(12)<< 20 ) + | ( get_alpha_index(13)<< 23 ) | ( get_alpha_index(14)<< 26 ) | ( get_alpha_index(15)<< 29 ); +} +void block_package5( out uint4 block, uint rotation, uint threadBase ) +{ + block.x = 0x20 | ( rotation << 6 ) + | ( ( get_end_point_l(0).r & 0xFE ) << 7 ) | ( ( get_end_point_h(0).r & 0xFE ) << 14 ) + | ( ( get_end_point_l(0).g & 0xFE ) << 21 ) | ( ( get_end_point_h(0).g & 0xFE ) << 28 ); + block.y = ( ( get_end_point_h(0).g & 0xFE ) >> 4 ) | ( ( get_end_point_l(0).b & 0xFE ) << 3 ) + | ( ( get_end_point_h(0).b & 0xFE ) << 10 ) | ( get_end_point_l(0).a << 18 ) | ( get_end_point_h(0).a << 26 ); + block.z = ( get_end_point_h(0).a >> 6 ) + | ( get_color_index(0) << 2 ) | ( get_color_index(1) << 3 ) | ( get_color_index(2) << 5 ) | ( get_color_index(3) << 7 ) + | ( get_color_index(4) << 9 ) | ( get_color_index(5) << 11 ) | ( get_color_index(6) << 13 ) | ( get_color_index(7) << 15 ) + | ( get_color_index(8) << 17 ) | ( get_color_index(9) << 19 ) | ( get_color_index(10)<< 21 ) | ( get_color_index(11)<< 23 ) + | ( get_color_index(12)<< 25 ) | ( get_color_index(13)<< 27 ) | ( get_color_index(14)<< 29 ) | ( get_color_index(15)<< 31 ); + block.w = ( get_color_index(15)>> 1 ) | ( get_alpha_index(0) << 1 ) | ( get_alpha_index(1) << 2 ) | ( get_alpha_index(2) << 4 ) + | ( get_alpha_index(3) << 6 ) | ( get_alpha_index(4) << 8 ) | ( get_alpha_index(5) << 10 ) | ( get_alpha_index(6) << 12 ) + | ( get_alpha_index(7) << 14 ) | ( get_alpha_index(8) << 16 ) | ( get_alpha_index(9) << 18 ) | ( get_alpha_index(10)<< 20 ) + | ( get_alpha_index(11)<< 22 ) | ( get_alpha_index(12)<< 24 ) | ( get_alpha_index(13)<< 26 ) | ( get_alpha_index(14)<< 28 ) + | ( get_alpha_index(15)<< 30 ); +} +void block_package6( out uint4 block, uint threadBase ) +{ + block.x = 0x40 + | ( ( get_end_point_l(0).r & 0xFE ) << 6 ) | ( ( get_end_point_h(0).r & 0xFE ) << 13 ) + | ( ( get_end_point_l(0).g & 0xFE ) << 20 ) | ( ( get_end_point_h(0).g & 0xFE ) << 27 ); + block.y = ( ( get_end_point_h(0).g & 0xFE ) >> 5 ) | ( ( get_end_point_l(0).b & 0xFE ) << 2 ) + | ( ( get_end_point_h(0).b & 0xFE ) << 9 ) | ( ( get_end_point_l(0).a & 0xFE ) << 16 ) + | ( ( get_end_point_h(0).a & 0xFE ) << 23 ) + | ( get_end_point_l(0).r & 0x01 ) << 31; + block.z = ( get_end_point_h(0).r & 0x01 ) + | ( get_color_index(0) << 1 ) | ( get_color_index(1) << 4 ) | ( get_color_index(2) << 8 ) | ( get_color_index(3) << 12 ) + | ( get_color_index(4) << 16 ) | ( get_color_index(5) << 20 ) | ( get_color_index(6) << 24 ) | ( get_color_index(7) << 28 ); + block.w = ( get_color_index(8) << 0 ) | ( get_color_index(9) << 4 ) | ( get_color_index(10)<< 8 ) | ( get_color_index(11)<< 12 ) + | ( get_color_index(12)<< 16 ) | ( get_color_index(13)<< 20 ) | ( get_color_index(14)<< 24 ) | ( get_color_index(15)<< 28 ); +} +void block_package7( out uint4 block, uint partition, uint threadBase ) +{ + block.x = 0x80 | ( partition << 8 ) + | ( ( get_end_point_l(0).r & 0xF8 ) << 11 ) | ( ( get_end_point_h(0).r & 0xF8 ) << 16 ) + | ( ( get_end_point_l(1).r & 0xF8 ) << 21 ) | ( ( get_end_point_h(1).r & 0xF8 ) << 26 ); + block.y = ( ( get_end_point_h(1).r & 0xF8 ) >> 6 ) | ( ( get_end_point_l(0).g & 0xF8 ) >> 1 ) + | ( ( get_end_point_h(0).g & 0xF8 ) << 4 ) | ( ( get_end_point_l(1).g & 0xF8 ) << 9 ) + | ( ( get_end_point_h(1).g & 0xF8 ) << 14 ) | ( ( get_end_point_l(0).b & 0xF8 ) << 19 ) + | ( ( get_end_point_h(0).b & 0xF8 ) << 24 ); + block.z = ( ( get_end_point_l(1).b & 0xF8 ) >> 3 ) | ( ( get_end_point_h(1).b & 0xF8 ) << 2 ) + | ( ( get_end_point_l(0).a & 0xF8 ) << 7 ) | ( ( get_end_point_h(0).a & 0xF8 ) << 12 ) + | ( ( get_end_point_l(1).a & 0xF8 ) << 17 ) | ( ( get_end_point_h(1).a & 0xF8 ) << 22 ) + | ( ( get_end_point_l(0).r & 0x04 ) << 28 ) | ( ( get_end_point_h(0).r & 0x04 ) << 29 ); + block.w = ( ( get_end_point_l(1).r & 0x04 ) >> 2 ) | ( ( get_end_point_h(1).r & 0x04 ) >> 1 ) + | ( get_color_index(0) << 2 ); + uint i = 1; + for ( ; i <= candidateFixUpIndex1DOrdered[partition][0]; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 + 1 ); + } + for ( ; i < 16; i ++ ) + { + block.w |= get_color_index(i) << ( i * 2 ); + } +} \ No newline at end of file diff --git a/Kits/DirectXTex/Shaders/CompileShaders.cmd b/Kits/DirectXTex/Shaders/CompileShaders.cmd new file mode 100644 index 0000000000000000000000000000000000000000..76e340df46dd7a6ce53669ba0558a3d035aaef85 --- /dev/null +++ b/Kits/DirectXTex/Shaders/CompileShaders.cmd @@ -0,0 +1,37 @@ +@echo off +rem THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +rem ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +rem THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +rem PARTICULAR PURPOSE. +rem +rem Copyright (c) Microsoft Corporation. All rights reserved. + +setlocal +set error=0 + +call :CompileShader BC7Encode TryMode456CS +call :CompileShader BC7Encode TryMode137CS +call :CompileShader BC7Encode TryMode02CS +call :CompileShader BC7Encode EncodeBlockCS + +call :CompileShader BC6HEncode TryModeG10CS +call :CompileShader BC6HEncode TryModeLE10CS +call :CompileShader BC6HEncode EncodeBlockCS + +echo. + +if %error% == 0 ( + echo Shaders compiled ok +) else ( + echo There were shader compilation errors! +) + +endlocal +exit /b + +:CompileShader +set fxc=fxc /nologo %1.hlsl /Tcs_4_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /E%2 /FhCompiled\%1_%2.inc /FdCompiled\%1_%2.pdb /Vn%1_%2 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b diff --git a/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_EncodeBlockCS.inc b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_EncodeBlockCS.inc new file mode 100644 index 0000000000000000000000000000000000000000..380f63eee91dffe6a1245626f14dd91cdaefa4fe --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_EncodeBlockCS.inc @@ -0,0 +1,22226 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { 0x0000cccc, 15, 0, 0}, + { 0x00008888, 15, 0, 0}, + { 0x0000eeee, 15, 0, 0}, + { 0x0000ecc8, 15, 1, 0}, + { 0x0000c880, 15, 1, 0}, + { 0x0000feec, 15, 1, 1}, + { 0x0000fec8, 15, 1, 1}, + { 0x0000ec80, 15, 2, 1}, + { 0x0000c800, 15, 2, 1}, + { 0x0000ffec, 15, 2, 1}, + { 0x0000fe80, 15, 2, 1}, + { 0x0000e800, 15, 2, 1}, + { 0x0000ffe8, 15, 3, 1}, + { 0x0000ff00, 15, 3, 1}, + { 0x0000fff0, 15, 3, 2}, + { 0x0000f000, 15, 3, 2}, + { 0x0000f710, 15, 4, 2}, + { 142, 2, 4, 2}, + { 0x00007100, 8, 4, 2}, + { 2254, 2, 4, 2}, + { 140, 2, 5, 2}, + { 0x00007310, 8, 5, 2}, + { 0x00003100, 8, 5, 2}, + { 0x00008cce, 15, 5, 3}, + { 2188, 2, 6, 3}, + { 0x00003110, 8, 6, 3}, + { 0x00006666, 2, 6, 3}, + { 0x0000366c, 2, 6, 3}, + { 6120, 8, 6, 3}, + { 4080, 8, 7, 3}, + { 0x0000718e, 2, 7, 3}, + { 0x0000399c, 2, 7, 3}, + { -1, 0, 7, 3}, + { -1, 0, 8, 4}, + { -1, 0, 8, 4}, + { -1, 0, 8, 4}, + { -1, 0, 8, 4}, + { -1, 0, 9, 4}, + { -1, 0, 9, 4}, + { -1, 0, 9, 4}, + { -1, 0, 9, 4}, + { 0, 0, 10, 4}, + { 0, 0, 10, 5}, + { -1, 0, 10, 5}, + { -1, 0, 10, 5}, + { -1, 0, 10, 5}, + { 0, 0, 11, 5}, + { 0, 0, 11, 5}, + { 0, 0, 11, 5}, + { 0, 0, 11, 5}, + { 0, 0, 12, 5}, + { 0, 0, 12, 6}, + { 0, 0, 12, 6}, + { 0, 0, 12, 6}, + { 0, 0, 13, 6}, + { 0, 0, 13, 6}, + { 0, 0, 13, 6}, + { 0, 0, 13, 6}, + { 0, 0, 14, 6}, + { 0, 0, 14, 6}, + { 0, 0, 14, 7}, + { 0, 0, 14, 7}, + { 0, 0, 15, 7}, + { 0, 0, 15, 7}, + { 10, 5, 5, 5}, + { 7, 6, 6, 6}, + { 11, 5, 4, 4}, + { 11, 4, 5, 4}, + { 11, 4, 4, 5}, + { 9, 5, 5, 5}, + { 8, 6, 5, 5}, + { 8, 5, 6, 5}, + { 8, 5, 5, 6}, + { 6, 6, 6, 6}, + { 10, 10, 10, 10}, + { 11, 9, 9, 9}, + { 12, 8, 8, 8}, + { 16, 4, 4, 4} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_structured t1, 16 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 18 +dcl_tgsm_structured g0, 84, 64 +dcl_thread_group 64, 1, 1 +ushr r0.x, vThreadIDInGroupFlattened.x, l(5) +ishl r0.y, vThreadGroupID.x, l(1) +iadd r0.y, r0.y, cb0[1].x +iadd r0.x, r0.x, r0.y +and r0.y, vThreadIDInGroupFlattened.x, l(32) +iadd r0.z, -r0.y, vThreadIDInGroupFlattened.x +ult r1.xyzw, r0.zzzz, l(16, 32, 2, 8) +if_nz r1.x + udiv r0.w, null, r0.x, cb0[0].y + imad r2.x, -r0.w, cb0[0].y, r0.x + ishl r2.x, r2.x, l(2) + ishl r0.w, r0.w, l(2) + and r2.y, r0.z, l(3) + iadd r2.x, r2.y, r2.x + ushr r3.x, r0.z, l(2) + iadd r2.y, r0.w, r3.x + mov r2.zw, l(0,0,0,0) + ld r2.xyzw, r2.xyzw, t0.xyzw + dp3 r0.w, r2.xyzx, l(0.212600, 0.715200, 0.072200, 0.000000) + store_structured g0.x, vThreadIDInGroupFlattened.x, l(36), r0.w + ushr r3.xyz, r2.xyzx, l(16) + and r3.xyz, r3.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + and r4.xyzw, r2.xxyy, l(0x7fffffff, 0x007fffff, 0x7fffffff, 0x007fffff) + ult r2.xy, l(0x47ffefff, 0x47ffefff, 0, 0), r4.xzxx + ult r5.xy, r4.xzxx, l(0x38800000, 0x38800000, 0, 0) + ushr r5.zw, r4.xxxz, l(23) + iadd r5.zw, -r5.zzzw, l(0, 0, 113, 113) + iadd r4.yw, r4.yyyw, l(0, 0x00800000, 0, 0x00800000) + ushr r6.x, r4.y, r5.z + ushr r6.y, r4.w, r5.w + iadd r4.xy, r4.xzxx, l(0xc8000000, 0xc8000000, 0, 0) + movc r4.xy, r5.xyxx, r6.xyxx, r4.xyxx + iadd r4.zw, r4.xxxy, l(0, 0, 4095, 4095) + ushr r4.xy, r4.xyxx, l(13) + and r4.xy, r4.xyxx, l(1, 1, 0, 0) + iadd r4.xy, r4.xyxx, r4.zwzz + ushr r4.xy, r4.xyxx, l(13) + and r4.xy, r4.xyxx, l(0x00007fff, 0x00007fff, 0, 0) + movc r2.xy, r2.xyxx, l(0x00007fff,0x00007fff,0,0), r4.xyxx + iadd r4.xy, r3.xyxx, r2.xyxx + and r2.xy, r2.zzzz, l(0x7fffffff, 0x007fffff, 0, 0) + ult r0.w, l(0x47ffefff), r2.x + ult r2.z, r2.x, l(0x38800000) + ushr r2.w, r2.x, l(23) + iadd r2.w, -r2.w, l(113) + iadd r2.y, r2.y, l(0x00800000) + ushr r2.y, r2.y, r2.w + iadd r2.x, r2.x, l(0xc8000000) + movc r2.x, r2.z, r2.y, r2.x + iadd r2.y, r2.x, l(4095) + ushr r2.x, r2.x, l(13) + and r2.x, r2.x, l(1) + iadd r2.x, r2.x, r2.y + ushr r2.x, r2.x, l(13) + and r2.x, r2.x, l(0x00007fff) + movc r0.w, r0.w, l(0x00007fff), r2.x + iadd r4.z, r3.z, r0.w + ieq r0.w, cb0[0].z, l(95) + ishl r2.xyz, r4.xyzx, l(6) + udiv r2.xyz, null, r2.xyzx, l(31, 31, 31, 0) + ult r3.xyz, r4.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + ieq r5.xyz, r4.xyzx, l(0x00007bff, 0x00007bff, 0x00007bff, 0) + ishl r4.xyz, r4.xyzx, l(5) + udiv r6.xyz, null, r4.xyzx, l(31, 31, 31, 0) + movc r6.xyz, r5.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r6.xyzx + and r4.xyz, r4.xyzx, l(0x000fffe0, 0x000fffe0, 0x000fffe0, 0) + udiv r4.xyz, null, r4.xyzx, l(31, 31, 31, 0) + ineg r4.xyz, r4.xyzx + movc r4.xyz, r5.xyzx, l(0xffff8001,0xffff8001,0xffff8001,0), r4.xyzx + movc r3.xyz, r3.xyzx, r6.xyzx, r4.xyzx + movc r2.xyz, r0.wwww, r2.xyzx, r3.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(12), r2.xyzx +endif +sync_g_t +ld_structured r2.xy, r0.x, l(4), t1.xyxx +if_nz r1.y + and r0.w, r0.z, l(15) + iadd r1.y, r0.w, r0.y + ld_structured r3.xyz, r1.y, l(12), g0.xyzx + ld_structured r3.w, r1.y, l(36), g0.xxxx + if_nz r1.x + ult r1.y, l(10), r2.x + if_nz r1.y + mov r4.xyzw, r3.xyzx + mov r5.xyzw, r3.yzww + else + ushr r1.y, icb[r2.y + 0].x, r0.z + and r1.y, r1.y, l(1) + movc r4.xyzw, r1.yyyy, l(0x7fffffff,0x7fffffff,0x7fffffff,-0.000000), r3.xyzx + movc r5.xyzw, r1.yyyy, l(-0.000000,-0.000000,340282346638528860000000000000000000000.000000,-340282346638528860000000000000000000000.000000), r3.yzww + endif + else + uge r1.y, l(10), r2.x + if_nz r1.y + ushr r0.w, icb[r2.y + 0].x, r0.w + and r0.w, r0.w, l(1) + ieq r0.w, r0.w, l(1) + movc r4.xyzw, r0.wwww, r3.xyzx, l(0x7fffffff,0x7fffffff,0x7fffffff,-0.000000) + movc r5.xyzw, r0.wwww, r3.yzww, l(-0.000000,-0.000000,340282346638528860000000000000000000000.000000,-340282346638528860000000000000000000000.000000) + else + mov r4.xyzw, l(0x7fffffff,0x7fffffff,0x7fffffff,-0.000000) + mov r5.xyzw, l(-0.000000,-0.000000,340282346638528860000000000000000000000.000000,-340282346638528860000000000000000000000.000000) + endif + endif + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r4.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(68), r5.xyzw +endif +sync_g_t +and r0.w, r0.z, l(15) +ult r3.xyzw, r0.wwww, l(8, 4, 2, 1) +if_nz r3.x + ld_structured r4.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(8) + ld_structured r5.x, r0.w, l(76), g0.xxxx + lt r1.y, r5.x, r4.x + if_nz r1.y + ld_structured r4.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r4.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(76), r5.x + endif + ld_structured r4.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r5.x, r0.w, l(80), g0.xxxx + lt r1.y, r4.x, r5.x + if_nz r1.y + ld_structured r4.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r4.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(80), r5.x + endif +endif +sync_g_t +if_nz r3.y + ld_structured r4.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(4) + ld_structured r5.x, r0.w, l(76), g0.xxxx + lt r1.y, r5.x, r4.x + if_nz r1.y + ld_structured r4.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r4.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(76), r5.x + endif + ld_structured r4.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r5.x, r0.w, l(80), g0.xxxx + lt r1.y, r4.x, r5.x + if_nz r1.y + ld_structured r4.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r4.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(80), r5.x + endif +endif +sync_g_t +if_nz r3.z + ld_structured r4.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(2) + ld_structured r5.x, r0.w, l(76), g0.xxxx + lt r1.y, r5.x, r4.x + if_nz r1.y + ld_structured r4.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r4.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(76), r5.x + endif + ld_structured r4.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r5.x, r0.w, l(80), g0.xxxx + lt r1.y, r4.x, r5.x + if_nz r1.y + ld_structured r4.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r4.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(80), r5.x + endif +endif +sync_g_t +if_nz r3.w + ld_structured r3.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(1) + ld_structured r4.x, r0.w, l(76), g0.xxxx + lt r1.y, r4.x, r3.x + if_nz r1.y + ld_structured r3.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r3.xyzx + endif + ld_structured r3.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r4.x, r0.w, l(80), g0.xxxx + lt r1.y, r3.x, r4.x + if_nz r1.y + ld_structured r3.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r3.xyzx + endif +endif +sync_g_t +if_nz r1.z + ishl r0.w, r0.z, l(4) + iadd r0.w, r0.w, r0.y + ld_structured r3.xyz, r0.w, l(52), g0.xyzx + ld_structured r4.xyz, r0.w, l(64), g0.xyzx + ieq r0.w, r0.z, l(1) + uge r1.y, l(10), r2.x + and r0.w, r0.w, r1.y + if_nz r0.w + mov r0.w, icb[r2.y + 0].y + else + mov r0.w, l(0) + endif + iadd r5.xyz, -r3.xyzx, r4.xyzx + itof r5.xyz, r5.xyzx + dp3 r1.y, r5.xyzx, r5.xyzx + iadd r0.w, r0.w, r0.y + ld_structured r6.xyz, r0.w, l(12), g0.xyzx + iadd r6.xyz, -r3.xyzx, r6.xyzx + itof r6.xyz, r6.xyzx + dp3 r0.w, r5.xyzx, r6.xyzx + lt r2.z, l(0.000000), r1.y + ge r2.w, r0.w, l(0.000000) + and r2.z, r2.w, r2.z + mul r0.w, r0.w, l(63.499989) + div r0.w, r0.w, r1.y + ftou r0.w, r0.w + ult r0.w, l(32), r0.w + and r0.w, r0.w, r2.z + mov r4.w, r3.x + mov r3.w, r4.x + movc r5.xyzw, r0.wwww, r4.xyzw, r3.xyzw + movc r2.zw, r0.wwww, r3.yyyz, r4.yyyz + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r5.xyzw + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(68), r2.zwzz +endif +sync_g_t +if_nz r1.x + ult r0.w, l(10), r2.x + if_nz r0.w + mov r1.x, l(0) + else + mov r1.x, icb[r2.y + 0].x + endif + ushr r1.x, r1.x, r0.z + and r1.x, r1.x, l(1) + if_nz r1.x + iadd r1.x, r0.y, l(1) + ld_structured r3.xyz, r1.x, l(64), g0.xyzx + ld_structured r4.xyz, r1.x, l(52), g0.xyzx + iadd r3.xyz, r3.xyzx, -r4.xyzx + itof r3.xyz, r3.xyzx + ld_structured r5.xyz, vThreadIDInGroupFlattened.x, l(12), g0.xyzx + iadd r4.xyz, -r4.xyzx, r5.xyzx + itof r4.xyz, r4.xyzx + dp3 r1.x, r3.xyzx, r4.xyzx + else + ld_structured r4.xyz, r0.y, l(64), g0.xyzx + ld_structured r5.xyz, r0.y, l(52), g0.xyzx + iadd r4.xyz, r4.xyzx, -r5.xyzx + itof r3.xyz, r4.xyzx + ld_structured r4.xyz, vThreadIDInGroupFlattened.x, l(12), g0.xyzx + iadd r4.xyz, -r5.xyzx, r4.xyzx + itof r4.xyz, r4.xyzx + dp3 r1.x, r3.xyzx, r4.xyzx + endif + dp3 r1.y, r3.xyzx, r3.xyzx + if_nz r0.w + ge r0.w, l(0.000000), r1.y + ge r2.z, l(0.000000), r1.x + or r0.w, r0.w, r2.z + lt r2.z, r1.x, r1.y + mul r2.w, r1.x, l(63.499989) + div r2.w, r2.w, r1.y + ftou r2.w, r2.w + movc r2.z, r2.z, icb[r2.w + 0].z, l(15) + movc r0.w, r0.w, l(0), r2.z + ishl r3.x, r0.w, l(1) + ult r2.z, r0.z, l(8) + ishl r2.w, r0.z, l(2) + ishl r4.x, r0.w, r2.w + iadd r2.w, r2.w, l(-32) + ishl r4.w, r0.w, r2.w + mov r4.yz, l(0,0,0,0) + movc r2.zw, r2.zzzz, r4.xxxy, r4.zzzw + mov r3.y, l(0) + movc r3.xy, r0.zzzz, r2.zwzz, r3.xyxx + else + ge r0.w, l(0.000000), r1.y + ge r2.z, l(0.000000), r1.x + or r0.w, r0.w, r2.z + lt r2.z, r1.x, r1.y + mul r1.x, r1.x, l(63.499989) + div r1.x, r1.x, r1.y + ftou r1.x, r1.x + movc r1.x, r2.z, icb[r1.x + 0].w, l(7) + movc r0.w, r0.w, l(0), r1.x + if_z r0.z + ishl r3.x, r0.w, l(18) + mov r3.y, l(0) + else + ult r1.x, r0.z, l(3) + if_nz r1.x + imad r1.x, r0.z, l(3), l(17) + ishl r3.x, r0.w, r1.x + mov r3.y, l(0) + else + ine r1.x, l(2), icb[r2.y + 0].y + ieq r1.y, l(15), icb[r2.y + 0].y + and r2.zw, r1.xxxy, l(0, 0, 1, 1) + ult r1.y, r0.z, l(5) + if_nz r1.y + imad r1.y, r0.z, l(3), r2.z + iadd r1.y, r1.y, l(16) + ishl r3.x, r0.w, r1.y + mov r3.y, l(0) + else + ieq r1.y, r0.z, l(5) + movc r4.x, r1.x, l(0), l(1) + ushr r4.y, r0.w, r4.x + ishl r4.z, r0.w, l(31) + movc r4.x, r1.x, l(0), r4.z + ult r1.x, r0.z, l(9) + imad r2.zw, r0.zzzz, l(0, 0, 3, 3), r2.zzzw + iadd r2.zw, r2.zzzw, l(0, 0, -16, -16) + ishl r2.z, r0.w, r2.z + ishl r0.w, r0.w, r2.w + movc r5.y, r1.x, r2.z, r0.w + mov r5.x, l(0) + movc r3.xy, r1.yyyy, r4.xyxx, r5.xyxx + endif + endif + endif + endif + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(24), r3.xyxx +else + mov r3.xy, l(0,0,0,0) +endif +sync_g_t +if_nz r1.w + ld_structured r4.xy, vThreadIDInGroupFlattened.x, l(24), g0.xyxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(8) + ld_structured r5.xy, r0.w, l(24), g0.xyxx + or r1.xy, r4.xyxx, r5.xyxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(24), r1.xyxx +endif +sync_g_t +ult r1.xy, r0.zzzz, l(4, 1, 0, 0) +if_nz r1.x + ld_structured r4.xy, vThreadIDInGroupFlattened.x, l(24), g0.xyxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(4) + ld_structured r5.xy, r0.w, l(24), g0.xyxx + or r1.xw, r4.xxxy, r5.xxxy + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(24), r1.xwxx +endif +sync_g_t +if_nz r1.z + ld_structured r4.xy, vThreadIDInGroupFlattened.x, l(24), g0.xyxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(2) + ld_structured r5.xy, r0.w, l(24), g0.xyxx + or r1.xw, r4.xxxy, r5.xxxy + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(24), r1.xwxx +endif +sync_g_t +if_nz r1.y + ld_structured r4.xy, vThreadIDInGroupFlattened.x, l(24), g0.xyxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(1) + ld_structured r5.xy, r0.w, l(24), g0.xyxx + or r3.xy, r4.xyxx, r5.xyxx +endif +sync_g_t +iadd r0.w, r2.x, l(-1) +ieq r1.xy, r0.zzzz, l(2, 3, 0, 0) +if_nz r1.x + ld_structured r4.xyz, r0.y, l(52), g0.xyzx + ld_structured r5.xyz, r0.y, l(64), g0.xyzx + ieq r1.x, cb0[0].z, l(95) + if_nz r1.x + ige r1.x, icb[r0.w + 64].x, l(15) + and r1.x, r1.x, l(1) + movc r6.xyz, r4.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r7.xyz, r5.xyzx, l(0,0,0,0), l(1,1,1,0) + or r6.xyz, r1.xxxx, r6.xyzx + or r7.xyz, r1.xxxx, r7.xyzx + ieq r8.xyz, r4.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ieq r9.xyz, r5.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ishl r1.x, l(1), icb[r0.w + 64].x + iadd r1.x, r1.x, l(-1) + ishl r10.xyz, r4.xyzx, icb[r0.w + 64].x + ishl r11.xyz, r5.xyzx, icb[r0.w + 64].x + ishr r10.xyz, r10.xyzx, l(16) + ishr r11.xyz, r11.xyzx, l(16) + movc r8.xyz, r8.xyzx, r1.xxxx, r10.xyzx + movc r9.xyz, r9.xyzx, r1.xxxx, r11.xyzx + movc r6.xyz, r6.xyzx, r4.xyzx, r8.xyzx + movc r7.xyz, r7.xyzx, r5.xyzx, r9.xyzx + else + ige r1.x, icb[r0.w + 64].x, l(16) + and r1.x, r1.x, l(1) + movc r8.xyz, r4.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r9.xyz, r5.xyzx, l(0,0,0,0), l(1,1,1,0) + or r8.xyz, r1.xxxx, r8.xyzx + or r9.xyz, r1.xxxx, r9.xyzx + ige r10.xyz, r4.xyzx, l(0, 0, 0, 0) + ige r11.xyz, r5.xyzx, l(0, 0, 0, 0) + ieq r12.xyz, r4.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r13.xyz, r5.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r1.x, l(-1), icb[r0.w + 64].x + ishl r1.w, l(1), r1.x + iadd r2.z, r1.w, l(-1) + ishl r14.xyz, r4.xyzx, r1.x + ishl r15.xyz, r5.xyzx, r1.x + ishr r14.xyz, r14.xyzx, l(15) + ishr r15.xyz, r15.xyzx, l(15) + movc r12.xyz, r12.xyzx, r2.zzzz, r14.xyzx + movc r13.xyz, r13.xyzx, r2.zzzz, r15.xyzx + ineg r14.xyz, r4.xyzx + ineg r15.xyz, r5.xyzx + ieq r16.xyz, r14.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r17.xyz, r15.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r1.w, -r1.w, l(1) + ishl r14.xyz, r14.xyzx, r1.x + ishl r15.xyz, r15.xyzx, r1.x + ishr r14.xyz, r14.xyzx, l(15) + ishr r15.xyz, r15.xyzx, l(15) + ineg r14.xyz, r14.xyzx + ineg r15.xyz, r15.xyzx + movc r14.xyz, r16.xyzx, r1.wwww, r14.xyzx + movc r15.xyz, r17.xyzx, r1.wwww, r15.xyzx + movc r10.xyz, r10.xyzx, r12.xyzx, r14.xyzx + movc r11.xyz, r11.xyzx, r13.xyzx, r15.xyzx + movc r6.xyz, r8.xyzx, r4.xyzx, r10.xyzx + movc r7.xyz, r9.xyzx, r5.xyzx, r11.xyzx + endif + iadd r4.xyz, -r6.xyzx, r7.xyzx + movc r4.xyz, icb[r0.w + 32].xxxx, r4.xyzx, r7.xyzx + mov r6.w, r4.x + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(68), r4.yzyy +endif +sync_g_t +if_nz r1.y + iadd r1.xy, r0.yyyy, l(2, 1, 0, 0) + ld_structured r4.xyz, r1.x, l(52), g0.xyzx + ld_structured r5.xyz, r1.y, l(52), g0.xyzx + ld_structured r6.xyz, r1.y, l(64), g0.xyzx + uge r1.x, l(10), r2.x + if_nz r1.x + ieq r1.x, cb0[0].z, l(95) + if_nz r1.x + ige r1.x, icb[r0.w + 64].x, l(15) + and r1.x, r1.x, l(1) + movc r7.xyz, r5.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r8.xyz, r6.xyzx, l(0,0,0,0), l(1,1,1,0) + or r7.xyz, r1.xxxx, r7.xyzx + or r1.xyw, r1.xxxx, r8.xyxz + ieq r8.xyz, r5.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ieq r9.xyz, r6.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ishl r2.z, l(1), icb[r0.w + 64].x + iadd r2.z, r2.z, l(-1) + ishl r10.xyz, r5.xyzx, icb[r0.w + 64].x + ishl r11.xyz, r6.xyzx, icb[r0.w + 64].x + ishr r10.xyz, r10.xyzx, l(16) + ishr r11.xyz, r11.xyzx, l(16) + movc r8.xyz, r8.xyzx, r2.zzzz, r10.xyzx + movc r9.xyz, r9.xyzx, r2.zzzz, r11.xyzx + movc r7.xyz, r7.xyzx, r5.xyzx, r8.xyzx + movc r1.xyw, r1.xyxw, r6.xyxz, r9.xyxz + else + ige r2.z, icb[r0.w + 64].x, l(16) + and r2.z, r2.z, l(1) + movc r8.xyz, r5.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r9.xyz, r6.xyzx, l(0,0,0,0), l(1,1,1,0) + or r8.xyz, r2.zzzz, r8.xyzx + or r9.xyz, r2.zzzz, r9.xyzx + ige r10.xyz, r5.xyzx, l(0, 0, 0, 0) + ige r11.xyz, r6.xyzx, l(0, 0, 0, 0) + ieq r12.xyz, r5.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r13.xyz, r6.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r2.z, l(-1), icb[r0.w + 64].x + ishl r2.w, l(1), r2.z + iadd r4.w, r2.w, l(-1) + ishl r14.xyz, r5.xyzx, r2.z + ishl r15.xyz, r6.xyzx, r2.z + ishr r14.xyz, r14.xyzx, l(15) + ishr r15.xyz, r15.xyzx, l(15) + movc r12.xyz, r12.xyzx, r4.wwww, r14.xyzx + movc r13.xyz, r13.xyzx, r4.wwww, r15.xyzx + ineg r14.xyz, r5.xyzx + ineg r15.xyz, r6.xyzx + ieq r16.xyz, r14.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r17.xyz, r15.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r2.w, -r2.w, l(1) + ishl r14.xyz, r14.xyzx, r2.z + ishl r15.xyz, r15.xyzx, r2.z + ishr r14.xyz, r14.xyzx, l(15) + ishr r15.xyz, r15.xyzx, l(15) + ineg r14.xyz, r14.xyzx + ineg r15.xyz, r15.xyzx + movc r14.xyz, r16.xyzx, r2.wwww, r14.xyzx + movc r15.xyz, r17.xyzx, r2.wwww, r15.xyzx + movc r10.xyz, r10.xyzx, r12.xyzx, r14.xyzx + movc r11.xyz, r11.xyzx, r13.xyzx, r15.xyzx + movc r7.xyz, r8.xyzx, r5.xyzx, r10.xyzx + movc r1.xyw, r9.xyxz, r6.xyxz, r11.xyxz + endif + iadd r5.xyz, -r4.xyzx, r7.xyzx + iadd r4.xyz, -r4.xyzx, r1.xywx + mov r5.w, r4.x + mov r7.w, r1.x + movc r5.xyzw, icb[r0.w + 32].xxxx, r5.xyzw, r7.xyzw + movc r1.xy, icb[r0.w + 32].xxxx, r4.yzyy, r1.ywyy + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r5.xyzw + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(68), r1.xyxx + endif +endif +sync_g_t +if_nz r1.z + iadd r1.x, vThreadIDInGroupFlattened.x, l(2) + ld_structured r4.xyz, r1.x, l(52), g0.xyzx + ld_structured r1.xyz, r1.x, l(64), g0.yzxx + if_z r0.z + ult r1.w, l(10), r2.x + if_nz r1.w + ishl r5.x, l(1), icb[r0.w + 64].x + ishl r5.y, l(1), icb[r0.w + 64].y + ishl r5.z, l(1), icb[r0.w + 64].z + ishl r5.w, l(1), icb[r0.w + 64].w + ige r6.xyz, r1.zxyz, l(0, 0, 0, 0) + iadd r7.xyz, l(-1, -1, -1, 0), icb[r0.w + 64].yzwy + ishl r8.x, l(1), r7.x + ishl r8.y, l(1), r7.y + ishl r8.z, l(1), r7.z + ige r7.xyz, r1.zxyz, r8.xyzx + iadd r9.xyz, r8.xyzx, l(-1, -1, -1, 0) + movc r7.xyz, r7.xyzx, r9.xyzx, r1.zxyz + ineg r9.xyz, r1.zxyz + ilt r9.xyz, r8.xyzx, r9.xyzx + iadd r5.xyzw, r5.xyzw, l(-1, -1, -1, -1) + and r5.yzw, r1.zzxy, r5.yyzw + movc r5.yzw, r9.xxyz, r8.xxyz, r5.yyzw + movc r5.yzw, r6.xxyz, r7.xxyz, r5.yyzw + mov r4.w, r1.z + and r6.xyzw, r4.xyzw, r5.xxxx + and r2.zw, r1.xxxy, r5.xxxx + mov r7.xyz, r6.xyzx + mov r7.w, r5.y + movc r4.xyzw, icb[r0.w + 32].xxxx, r7.xyzw, r6.xyzw + movc r1.xy, icb[r0.w + 32].xxxx, r5.zwzz, r2.zwzz + else + if_nz icb[r0.w + 32].x + ishl r5.x, l(1), icb[r0.w + 64].x + ishl r5.y, l(1), icb[r0.w + 64].y + ishl r5.z, l(1), icb[r0.w + 64].z + ishl r5.w, l(1), icb[r0.w + 64].w + iadd r5.xyzw, r5.xyzw, l(-1, -1, -1, -1) + and r4.xyz, r4.xyzx, r5.xxxx + ige r6.xyz, r1.zxyz, l(0, 0, 0, 0) + iadd r7.xyz, l(-1, -1, -1, 0), icb[r0.w + 64].yzwy + ishl r8.x, l(1), r7.x + ishl r8.y, l(1), r7.y + ishl r8.z, l(1), r7.z + ige r7.xyz, r1.zxyz, r8.xyzx + iadd r9.xyz, r8.xyzx, l(-1, -1, -1, 0) + movc r7.xyz, r7.xyzx, r9.xyzx, r1.zxyz + ineg r9.xyz, r1.zxyz + ilt r9.xyz, r8.xyzx, r9.xyzx + and r5.xyz, r1.zxyz, r5.yzwy + movc r5.xyz, r9.xyzx, r8.xyzx, r5.xyzx + movc r1.xyz, r6.yzxy, r7.yzxy, r5.yzxy + mov r4.w, r1.z + else + ishl r1.w, l(1), icb[r0.w + 64].x + iadd r1.w, r1.w, l(-1) + mov r4.w, r1.z + and r4.xyzw, r1.wwww, r4.xyzw + and r1.xy, r1.wwww, r1.xyxx + endif + endif + else + uge r1.w, l(10), r2.x + if_nz r1.w + if_nz icb[r0.w + 32].x + ige r5.xyz, r4.xyzx, l(0, 0, 0, 0) + iadd r6.xyz, l(-1, -1, -1, 0), icb[r0.w + 64].yzwy + ishl r7.x, l(1), r6.x + ishl r7.y, l(1), r6.y + ishl r7.z, l(1), r6.z + ige r6.xyz, r4.xyzx, r7.xyzx + iadd r8.xyz, r7.xyzx, l(-1, -1, -1, 0) + movc r6.xyz, r6.xyzx, r8.xyzx, r4.xyzx + ineg r9.xyz, r4.xyzx + ilt r9.xyz, r7.xyzx, r9.xyzx + ishl r10.x, l(1), icb[r0.w + 64].y + ishl r10.y, l(1), icb[r0.w + 64].z + ishl r10.z, l(1), icb[r0.w + 64].w + iadd r10.xyz, r10.xyzx, l(-1, -1, -1, 0) + and r11.xyz, r4.xyzx, r10.xyzx + movc r9.xyz, r9.xyzx, r7.xyzx, r11.xyzx + movc r4.xyz, r5.xyzx, r6.xyzx, r9.xyzx + ige r5.xyz, r1.zxyz, l(0, 0, 0, 0) + ige r6.xyz, r1.zxyz, r7.xyzx + movc r6.xyz, r6.xyzx, r8.xyzx, r1.zxyz + ineg r8.xyz, r1.zxyz + ilt r8.xyz, r7.xyzx, r8.xyzx + and r9.xyz, r1.zxyz, r10.xyzx + movc r7.xyz, r8.xyzx, r7.xyzx, r9.xyzx + movc r1.xyz, r5.yzxy, r6.yzxy, r7.yzxy + mov r4.w, r1.z + else + ishl r0.w, l(1), icb[r0.w + 64].x + iadd r0.w, r0.w, l(-1) + mov r4.w, r1.z + and r4.xyzw, r0.wwww, r4.xyzw + and r1.xy, r0.wwww, r1.xyxx + endif + else + mov r4.w, r1.z + endif + endif + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r4.xyzw + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(68), r1.xyxx +endif +sync_g_t +if_z r0.z + ld_structured r1.xyzw, r0.y, l(52), g0.xyzw + ld_structured r4.xy, r0.y, l(68), g0.xyxx + ult r0.z, l(10), r2.x + if_nz r0.z + and r3.w, r3.x, l(-2) + ieq r0.z, r2.x, l(11) + if_nz r0.z + ishl r5.x, r1.x, l(5) + ishl r5.y, r1.y, l(15) + ishl r5.z, r1.z, l(25) + ishl r5.w, r1.w, l(3) + and r5.xyzw, r5.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.z, r5.x, l(3) + ishr r0.w, r1.x, l(1) + ishr r2.z, r1.x, l(2) + ishr r2.w, r1.x, l(3) + ishr r4.z, r1.x, l(4) + ishl r6.x, r0.w, l(6) + ishl r6.y, r2.z, l(7) + ishl r6.z, r2.w, l(8) + ishl r6.w, r4.z, l(9) + and r6.xyzw, r6.xyzw, l(64, 128, 256, 512) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(5) + ishr r2.z, r1.x, l(6) + ishr r2.w, r1.x, l(7) + ishr r4.z, r1.x, l(8) + ishl r6.x, r0.w, l(10) + ishl r6.y, r2.z, l(11) + ishl r6.z, r2.w, l(12) + ishl r6.w, r4.z, l(13) + and r6.xyzw, r6.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(9) + ishr r2.z, r1.y, l(1) + ishr r2.w, r1.y, l(2) + ishr r4.z, r1.y, l(3) + ishl r6.x, r0.w, l(14) + ishl r6.y, r2.z, l(16) + ishl r6.z, r2.w, l(17) + ishl r6.w, r4.z, l(18) + and r6.xyzw, r6.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(4) + ishr r2.z, r1.y, l(5) + ishr r2.w, r1.y, l(6) + ishr r4.z, r1.y, l(7) + ishl r6.x, r0.w, l(19) + ishl r6.y, r2.z, l(20) + ishl r6.z, r2.w, l(21) + ishl r6.w, r4.z, l(22) + and r6.xyzw, r6.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(8) + ishr r2.z, r1.y, l(9) + ishr r2.w, r1.z, l(1) + ishr r4.z, r1.z, l(2) + ishl r6.x, r0.w, l(23) + ishl r6.y, r2.z, l(24) + ishl r6.z, r2.w, l(26) + ishl r6.w, r4.z, l(27) + and r6.xyzw, r6.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.z, l(3) + ishr r2.z, r1.z, l(4) + ishr r2.w, r1.z, l(5) + ishr r4.z, r1.z, l(6) + ishl r5.x, r0.w, l(28) + ishl r5.y, r2.z, l(29) + ishl r5.z, r2.w, l(30) + ishl r0.w, r4.z, l(31) + and r5.xyz, r5.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r3.x, r0.w, r0.z + ishr r0.z, r1.z, l(7) + ishr r0.w, r1.z, l(8) + ishr r2.z, r1.z, l(9) + ishr r2.w, r1.w, l(1) + and r0.z, r0.z, l(1) + ishl r5.x, r0.w, l(1) + ishl r5.y, r2.z, l(2) + ishl r5.z, r2.w, l(4) + and r5.xyz, r5.xyzx, l(2, 4, 16, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.w, r0.z + iadd r0.z, r5.z, r0.z + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + ishr r2.w, r1.w, l(4) + ishr r4.z, r1.w, l(5) + ishl r5.x, r0.w, l(5) + ishl r5.y, r2.z, l(6) + ishl r5.z, r2.w, l(7) + ishl r5.w, r4.z, l(8) + and r5.xyzw, r5.xyzw, l(32, 64, 128, 256) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.w, l(6) + ishr r2.z, r1.w, l(7) + ishr r2.w, r1.w, l(8) + ishr r4.z, r1.w, l(9) + ishl r5.x, r0.w, l(9) + ishl r5.y, r2.z, l(10) + ishl r5.z, r2.w, l(11) + ishl r5.w, r4.z, l(12) + and r5.xyzw, r5.xyzw, l(512, 1024, 2048, 4096) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishl r5.x, r4.x, l(13) + ishl r5.y, r4.y, l(23) + and r2.zw, r5.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.z, r0.z, r2.z + ishr r0.w, r4.x, l(1) + ishr r2.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishr r4.w, r4.x, l(4) + ishl r5.x, r0.w, l(14) + ishl r5.y, r2.z, l(15) + ishl r5.z, r4.z, l(16) + ishl r5.w, r4.w, l(17) + and r5.xyzw, r5.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r4.x, l(5) + ishr r2.z, r4.x, l(6) + ishr r4.z, r4.x, l(7) + ishr r4.w, r4.x, l(8) + ishl r5.x, r0.w, l(18) + ishl r5.y, r2.z, l(19) + ishl r5.z, r4.z, l(20) + ishl r5.w, r4.w, l(21) + and r5.xyzw, r5.xyzw, l(0x00040000, 0x00080000, 0x00100000, 0x00200000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r4.x, l(9) + ishr r2.z, r4.y, l(1) + ishr r4.z, r4.y, l(2) + ishr r4.w, r4.y, l(3) + ishl r5.x, r0.w, l(22) + ishl r5.y, r2.z, l(24) + ishl r5.z, r4.z, l(25) + ishl r5.w, r4.w, l(26) + and r5.xyzw, r5.xyzw, l(0x00400000, 0x01000000, 0x02000000, 0x04000000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r2.w, r0.z + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r4.y, l(4) + ishr r2.z, r4.y, l(5) + ishr r2.w, r4.y, l(6) + ishr r4.z, r4.y, l(7) + ishl r5.x, r0.w, l(27) + ishl r5.y, r2.z, l(28) + ishl r5.z, r2.w, l(29) + ishl r5.w, r4.z, l(30) + and r5.xyzw, r5.xyzw, l(0x08000000, 0x10000000, 0x20000000, 0x40000000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r4.y, l(8) + ishr r2.z, r4.y, l(9) + ishl r0.w, r0.w, l(31) + iadd r3.z, r0.w, r0.z + and r0.z, r2.z, l(1) + iadd r3.w, r0.z, r3.w + else + ieq r0.z, r2.x, l(12) + if_nz r0.z + ishl r5.x, r1.x, l(5) + ishl r5.y, r1.y, l(15) + ishl r5.z, r1.z, l(25) + ishl r5.w, r1.w, l(3) + and r5.xyzw, r5.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.z, r5.x, l(7) + ishr r0.w, r1.x, l(1) + ishr r2.z, r1.x, l(2) + ishr r2.w, r1.x, l(3) + ishr r4.z, r1.x, l(4) + ishl r6.x, r0.w, l(6) + ishl r6.y, r2.z, l(7) + ishl r6.z, r2.w, l(8) + ishl r6.w, r4.z, l(9) + and r6.xyzw, r6.xyzw, l(64, 128, 256, 512) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(5) + ishr r2.z, r1.x, l(6) + ishr r2.w, r1.x, l(7) + ishr r4.z, r1.x, l(8) + ishl r6.x, r0.w, l(10) + ishl r6.y, r2.z, l(11) + ishl r6.z, r2.w, l(12) + ishl r6.w, r4.z, l(13) + and r6.xyzw, r6.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(9) + ishr r2.z, r1.y, l(1) + ishr r2.w, r1.y, l(2) + ishr r4.z, r1.y, l(3) + ishl r6.x, r0.w, l(14) + ishl r6.y, r2.z, l(16) + ishl r6.z, r2.w, l(17) + ishl r6.w, r4.z, l(18) + and r6.xyzw, r6.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(4) + ishr r2.z, r1.y, l(5) + ishr r2.w, r1.y, l(6) + ishr r4.z, r1.y, l(7) + ishl r6.x, r0.w, l(19) + ishl r6.y, r2.z, l(20) + ishl r6.z, r2.w, l(21) + ishl r6.w, r4.z, l(22) + and r6.xyzw, r6.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(8) + ishr r2.z, r1.y, l(9) + ishr r2.w, r1.z, l(1) + ishr r4.z, r1.z, l(2) + ishl r6.x, r0.w, l(23) + ishl r6.y, r2.z, l(24) + ishl r6.z, r2.w, l(26) + ishl r6.w, r4.z, l(27) + and r6.xyzw, r6.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.z, l(3) + ishr r2.z, r1.z, l(4) + ishr r2.w, r1.z, l(5) + ishr r4.z, r1.z, l(6) + ishl r5.x, r0.w, l(28) + ishl r5.y, r2.z, l(29) + ishl r5.z, r2.w, l(30) + ishl r0.w, r4.z, l(31) + and r5.xyz, r5.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r3.x, r0.w, r0.z + ishr r0.z, r1.z, l(7) + ishr r0.w, r1.z, l(8) + ishr r2.z, r1.z, l(9) + ishr r2.w, r1.w, l(1) + and r0.z, r0.z, l(1) + ishl r5.x, r0.w, l(1) + ishl r5.y, r2.z, l(2) + ishl r5.z, r2.w, l(4) + and r5.xyz, r5.xyzx, l(2, 4, 16, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.w, r0.z + iadd r0.z, r5.z, r0.z + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + ishr r2.w, r1.w, l(4) + ishr r4.z, r1.w, l(5) + ishl r5.x, r0.w, l(5) + ishl r5.y, r2.z, l(6) + ishl r5.z, r2.w, l(7) + ishl r5.w, r4.z, l(8) + and r5.xyzw, r5.xyzw, l(32, 64, 128, 256) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.w, l(6) + ishr r2.z, r1.w, l(7) + ishr r2.w, r1.w, l(8) + ishr r4.z, r1.x, l(10) + ishl r5.x, r0.w, l(9) + ishl r5.y, r2.z, l(10) + ishl r5.z, r2.w, l(11) + ishl r5.w, r4.z, l(12) + and r5.xyzw, r5.xyzw, l(512, 1024, 2048, 4096) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishl r5.x, r4.x, l(13) + ishl r5.y, r4.y, l(23) + and r2.zw, r5.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.z, r0.z, r2.z + ishr r0.w, r4.x, l(1) + ishr r2.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishr r4.w, r4.x, l(4) + ishl r5.x, r0.w, l(14) + ishl r5.y, r2.z, l(15) + ishl r5.z, r4.z, l(16) + ishl r5.w, r4.w, l(17) + and r5.xyzw, r5.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r4.x, l(5) + ishr r2.z, r4.x, l(6) + ishr r4.z, r4.x, l(7) + ishr r4.w, r4.x, l(8) + ishl r5.x, r0.w, l(18) + ishl r5.y, r2.z, l(19) + ishl r5.z, r4.z, l(20) + ishl r5.w, r4.w, l(21) + and r5.xyzw, r5.xyzw, l(0x00040000, 0x00080000, 0x00100000, 0x00200000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r4.zw, r1.yyyz, l(10) + ishl r0.w, r4.z, l(22) + and r0.w, r0.w, l(0x00400000) + iadd r0.z, r0.w, r0.z + iadd r0.z, r2.w, r0.z + ishr r0.w, r4.y, l(1) + ishr r2.z, r4.y, l(2) + ishr r2.w, r4.y, l(3) + ishr r4.z, r4.y, l(4) + ishl r5.x, r0.w, l(24) + ishl r5.y, r2.z, l(25) + ishl r5.z, r2.w, l(26) + ishl r5.w, r4.z, l(27) + and r5.xyzw, r5.xyzw, l(0x01000000, 0x02000000, 0x04000000, 0x08000000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r4.y, l(5) + ishr r2.z, r4.y, l(6) + ishr r2.w, r4.y, l(7) + ishr r4.z, r4.y, l(8) + ishl r5.x, r0.w, l(28) + ishl r5.y, r2.z, l(29) + ishl r5.z, r2.w, l(30) + ishl r0.w, r4.z, l(31) + and r5.xyz, r5.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r3.z, r0.w, r0.z + and r0.z, r4.w, l(1) + iadd r3.w, r0.z, r3.w + else + ieq r0.z, r2.x, l(13) + if_nz r0.z + ishl r5.x, r1.x, l(5) + ishl r5.y, r1.y, l(15) + ishl r5.z, r1.z, l(25) + ishl r5.w, r1.w, l(3) + and r5.xyzw, r5.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.z, r5.x, l(11) + ishr r0.w, r1.x, l(1) + ishr r2.z, r1.x, l(2) + ishr r2.w, r1.x, l(3) + ishr r4.z, r1.x, l(4) + ishl r6.x, r0.w, l(6) + ishl r6.y, r2.z, l(7) + ishl r6.z, r2.w, l(8) + ishl r6.w, r4.z, l(9) + and r6.xyzw, r6.xyzw, l(64, 128, 256, 512) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(5) + ishr r2.z, r1.x, l(6) + ishr r2.w, r1.x, l(7) + ishr r4.z, r1.x, l(8) + ishl r6.x, r0.w, l(10) + ishl r6.y, r2.z, l(11) + ishl r6.z, r2.w, l(12) + ishl r6.w, r4.z, l(13) + and r6.xyzw, r6.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(9) + ishr r2.z, r1.y, l(1) + ishr r2.w, r1.y, l(2) + ishr r4.z, r1.y, l(3) + ishl r6.x, r0.w, l(14) + ishl r6.y, r2.z, l(16) + ishl r6.z, r2.w, l(17) + ishl r6.w, r4.z, l(18) + and r6.xyzw, r6.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(4) + ishr r2.z, r1.y, l(5) + ishr r2.w, r1.y, l(6) + ishr r4.z, r1.y, l(7) + ishl r6.x, r0.w, l(19) + ishl r6.y, r2.z, l(20) + ishl r6.z, r2.w, l(21) + ishl r6.w, r4.z, l(22) + and r6.xyzw, r6.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(8) + ishr r2.z, r1.y, l(9) + ishr r2.w, r1.z, l(1) + ishr r4.z, r1.z, l(2) + ishl r6.x, r0.w, l(23) + ishl r6.y, r2.z, l(24) + ishl r6.z, r2.w, l(26) + ishl r6.w, r4.z, l(27) + and r6.xyzw, r6.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.z, l(3) + ishr r2.z, r1.z, l(4) + ishr r2.w, r1.z, l(5) + ishr r4.z, r1.z, l(6) + ishl r5.x, r0.w, l(28) + ishl r5.y, r2.z, l(29) + ishl r5.z, r2.w, l(30) + ishl r0.w, r4.z, l(31) + and r5.xyz, r5.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r3.x, r0.w, r0.z + ishr r0.z, r1.z, l(7) + ishr r0.w, r1.z, l(8) + ishr r2.z, r1.z, l(9) + ishr r2.w, r1.w, l(1) + and r0.z, r0.z, l(1) + ishl r5.x, r0.w, l(1) + ishl r5.y, r2.z, l(2) + ishl r5.z, r2.w, l(4) + and r5.xyz, r5.xyzx, l(2, 4, 16, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.w, r0.z + iadd r0.z, r5.z, r0.z + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + ishr r2.w, r1.w, l(4) + ishr r4.z, r1.w, l(5) + ishl r5.x, r0.w, l(5) + ishl r5.y, r2.z, l(6) + ishl r5.z, r2.w, l(7) + ishl r5.w, r4.z, l(8) + and r5.xyzw, r5.xyzw, l(32, 64, 128, 256) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.w, l(6) + ishr r2.z, r1.w, l(7) + ishr r2.w, r1.x, l(10) + ishr r4.z, r1.y, l(11) + ishl r5.x, r0.w, l(9) + ishl r5.y, r2.z, l(10) + ishl r5.z, r2.w, l(12) + ishl r5.w, r4.z, l(21) + and r5.xyzw, r5.xyzw, l(512, 1024, 4096, 0x00200000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + and r0.w, r1.x, l(2048) + iadd r0.z, r0.w, r0.z + iadd r0.z, r5.z, r0.z + ishl r5.x, r4.x, l(13) + ishl r5.y, r4.y, l(23) + and r2.zw, r5.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.z, r0.z, r2.z + ishr r0.w, r4.x, l(1) + ishr r2.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishr r4.w, r4.x, l(4) + ishl r6.x, r0.w, l(14) + ishl r6.y, r2.z, l(15) + ishl r6.z, r4.z, l(16) + ishl r6.w, r4.w, l(17) + and r6.xyzw, r6.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r4.x, l(5) + ishr r2.z, r4.x, l(6) + ishr r4.z, r4.x, l(7) + ishr r4.w, r4.y, l(1) + ishl r6.x, r0.w, l(18) + ishl r6.y, r2.z, l(19) + ishl r6.z, r4.z, l(20) + ishl r6.w, r4.w, l(24) + and r6.xyzw, r6.xyzw, l(0x00040000, 0x00080000, 0x00100000, 0x01000000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r4.zw, r1.yyyz, l(10) + ishr r0.w, r1.z, l(11) + ishl r2.z, r4.z, l(22) + ishl r0.w, r0.w, l(31) + and r2.z, r2.z, l(0x00400000) + iadd r0.z, r0.z, r2.z + iadd r0.z, r2.w, r0.z + iadd r0.z, r6.w, r0.z + ishr r2.z, r4.y, l(2) + ishr r2.w, r4.y, l(3) + ishr r4.z, r4.y, l(4) + ishr r5.x, r4.y, l(5) + ishl r6.x, r2.z, l(25) + ishl r6.y, r2.w, l(26) + ishl r6.z, r4.z, l(27) + ishl r6.w, r5.x, l(28) + and r5.xyzw, r6.xyzw, l(0x02000000, 0x04000000, 0x08000000, 0x10000000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r2.z, r4.y, l(6) + ishr r2.w, r4.y, l(7) + ishl r5.x, r2.z, l(29) + ishl r5.y, r2.w, l(30) + and r2.zw, r5.xxxy, l(0, 0, 0x20000000, 0x40000000) + iadd r0.z, r0.z, r2.z + iadd r0.z, r2.w, r0.z + iadd r3.z, r0.w, r0.z + and r0.z, r4.w, l(1) + iadd r3.w, r0.z, r3.w + else + ieq r0.z, r2.x, l(14) + if_nz r0.z + ishl r5.x, r1.x, l(5) + ishl r5.y, r1.y, l(15) + ishl r5.z, r1.z, l(25) + ishl r5.w, r1.w, l(3) + and r5.xyzw, r5.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.z, r5.x, l(15) + ishr r0.w, r1.x, l(1) + ishr r2.z, r1.x, l(2) + ishr r2.w, r1.x, l(3) + ishr r4.z, r1.x, l(4) + ishl r6.x, r0.w, l(6) + ishl r6.y, r2.z, l(7) + ishl r6.z, r2.w, l(8) + ishl r6.w, r4.z, l(9) + and r6.xyzw, r6.xyzw, l(64, 128, 256, 512) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(5) + ishr r2.z, r1.x, l(6) + ishr r2.w, r1.x, l(7) + ishr r4.z, r1.x, l(8) + ishl r6.x, r0.w, l(10) + ishl r6.y, r2.z, l(11) + ishl r6.z, r2.w, l(12) + ishl r6.w, r4.z, l(13) + and r6.xyzw, r6.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.x, l(9) + ishr r2.z, r1.y, l(1) + ishr r2.w, r1.y, l(2) + ishr r4.z, r1.y, l(3) + ishl r6.x, r0.w, l(14) + ishl r6.y, r2.z, l(16) + ishl r6.z, r2.w, l(17) + ishl r6.w, r4.z, l(18) + and r6.xyzw, r6.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(4) + ishr r2.z, r1.y, l(5) + ishr r2.w, r1.y, l(6) + ishr r4.z, r1.y, l(7) + ishl r6.x, r0.w, l(19) + ishl r6.y, r2.z, l(20) + ishl r6.z, r2.w, l(21) + ishl r6.w, r4.z, l(22) + and r6.xyzw, r6.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.y, l(8) + ishr r2.z, r1.y, l(9) + ishr r2.w, r1.z, l(1) + ishr r4.z, r1.z, l(2) + ishl r6.x, r0.w, l(23) + ishl r6.y, r2.z, l(24) + ishl r6.z, r2.w, l(26) + ishl r6.w, r4.z, l(27) + and r6.xyzw, r6.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r1.z, l(3) + ishr r2.z, r1.z, l(4) + ishr r2.w, r1.z, l(5) + ishr r4.z, r1.z, l(6) + ishl r5.x, r0.w, l(28) + ishl r5.y, r2.z, l(29) + ishl r5.z, r2.w, l(30) + ishl r0.w, r4.z, l(31) + and r5.xyz, r5.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r3.x, r0.w, r0.z + ishr r0.z, r1.z, l(7) + ishr r0.w, r1.z, l(8) + ishr r2.z, r1.z, l(9) + ishr r2.w, r1.w, l(1) + and r0.z, r0.z, l(1) + ishl r5.x, r0.w, l(1) + ishl r5.y, r2.z, l(2) + ishl r5.z, r2.w, l(4) + and r5.xyz, r5.xyzx, l(2, 4, 16, 0) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.w, r0.z + iadd r0.z, r5.z, r0.z + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + ishr r2.w, r1.x, l(15) + ishr r4.z, r1.x, l(14) + ishl r5.x, r0.w, l(5) + ishl r5.y, r2.z, l(6) + ishl r5.z, r2.w, l(7) + ishl r5.w, r4.z, l(8) + and r5.xyzw, r5.xyzw, l(32, 64, 128, 256) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.x, l(13) + ishr r2.z, r1.x, l(12) + ishr r2.w, r1.x, l(10) + ishr r4.z, r1.y, l(15) + ishl r5.x, r0.w, l(9) + ishl r5.y, r2.z, l(10) + ishl r5.z, r2.w, l(12) + ishl r5.w, r4.z, l(17) + and r5.xyzw, r5.xyzw, l(512, 1024, 4096, 0x00020000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + and r0.w, r1.x, l(2048) + iadd r0.z, r0.w, r0.z + iadd r0.z, r5.z, r0.z + ishl r5.x, r4.x, l(13) + ishl r5.y, r4.y, l(23) + and r2.zw, r5.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.z, r0.z, r2.z + ishr r4.zw, r4.xxxy, l(1) + ishr r0.w, r4.x, l(2) + ishr r2.z, r4.x, l(3) + ishl r6.x, r4.z, l(14) + ishl r6.y, r0.w, l(15) + ishl r6.z, r2.z, l(16) + ishl r6.w, r4.w, l(24) + and r6.xyzw, r6.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x01000000) + iadd r0.z, r0.z, r6.x + iadd r0.z, r6.y, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.y, l(14) + ishr r2.z, r1.y, l(13) + ishr r4.z, r1.y, l(12) + ishr r4.w, r1.y, l(11) + ishl r5.x, r0.w, l(18) + ishl r5.y, r2.z, l(19) + ishl r5.z, r4.z, l(20) + ishl r5.w, r4.w, l(21) + and r5.xyzw, r5.xyzw, l(0x00040000, 0x00080000, 0x00100000, 0x00200000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.y, l(10) + ishr r2.z, r1.z, l(15) + ishr r4.z, r1.z, l(14) + ishr r4.w, r1.z, l(13) + ishl r5.x, r0.w, l(22) + ishl r5.y, r2.z, l(27) + ishl r5.z, r4.z, l(28) + ishl r5.w, r4.w, l(29) + and r5.xyzw, r5.xyzw, l(0x00400000, 0x08000000, 0x10000000, 0x20000000) + iadd r0.z, r0.z, r5.x + iadd r0.z, r2.w, r0.z + iadd r0.z, r6.w, r0.z + ishr r0.w, r4.y, l(2) + ishr r2.z, r4.y, l(3) + ishl r6.x, r0.w, l(25) + ishl r6.y, r2.z, l(26) + and r2.zw, r6.xxxy, l(0, 0, 0x02000000, 0x04000000) + iadd r0.z, r0.z, r2.z + iadd r0.z, r2.w, r0.z + iadd r0.z, r5.y, r0.z + iadd r0.z, r5.z, r0.z + iadd r0.z, r5.w, r0.z + ishr r0.w, r1.z, l(12) + ishr r2.z, r1.z, l(11) + ishr r2.w, r1.z, l(10) + ishl r0.w, r0.w, l(30) + ishl r2.z, r2.z, l(31) + and r0.w, r0.w, l(0x40000000) + iadd r0.z, r0.w, r0.z + iadd r3.z, r2.z, r0.z + and r0.z, r2.w, l(1) + iadd r3.w, r0.z, r3.w + else + mov r3.xz, l(0,0,0,0) + endif + endif + endif + endif + else + iadd r0.y, r0.y, l(1) + ld_structured r5.xyzw, r0.y, l(52), g0.xyzw + ld_structured r6.xy, r0.y, l(68), g0.xyxx + and r3.w, r3.x, l(0xfffc0000) + ieq r0.y, r2.x, l(1) + if_nz r0.y + ishr r0.yz, r5.yyzy, l(4) + ishr r0.w, r5.y, l(1) + ishr r2.z, r5.y, l(2) + ishl r7.x, r0.y, l(2) + ishl r7.y, r0.z, l(3) + ishl r7.z, r0.w, l(10) + ishl r7.w, r2.z, l(11) + and r7.xyzw, r7.xyzw, l(4, 8, 1024, 2048) + iadd r0.y, r7.y, r7.x + and r0.z, r6.y, l(16) + iadd r0.y, r0.z, r0.y + ishl r8.x, r1.x, l(5) + ishl r8.y, r1.y, l(15) + ishl r8.z, r1.z, l(25) + ishl r8.w, r1.w, l(3) + and r8.xyzw, r8.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r0.y, r8.x + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r9.x, r0.z, l(6) + ishl r9.y, r0.w, l(7) + ishl r9.z, r2.z, l(8) + ishl r9.w, r2.w, l(9) + and r9.xyzw, r9.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.x, l(8) + ishl r9.x, r0.z, l(10) + ishl r9.y, r0.w, l(11) + ishl r9.z, r2.z, l(12) + ishl r9.w, r2.w, l(13) + and r9.xyzw, r9.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.x, l(9) + ishr r0.w, r1.y, l(1) + ishr r2.z, r1.y, l(2) + ishr r2.w, r1.y, l(3) + ishl r9.x, r0.z, l(14) + ishl r9.y, r0.w, l(16) + ishl r9.z, r2.z, l(17) + ishl r9.w, r2.w, l(18) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.y, l(4) + ishr r0.w, r1.y, l(5) + ishr r2.z, r1.y, l(6) + ishr r2.w, r1.y, l(7) + ishl r9.x, r0.z, l(19) + ishl r9.y, r0.w, l(20) + ishl r9.z, r2.z, l(21) + ishl r9.w, r2.w, l(22) + and r9.xyzw, r9.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.y, l(8) + ishr r0.w, r1.y, l(9) + ishr r2.z, r1.z, l(1) + ishr r2.w, r1.z, l(2) + ishl r9.x, r0.z, l(23) + ishl r9.y, r0.w, l(24) + ishl r9.z, r2.z, l(26) + ishl r9.w, r2.w, l(27) + and r9.xyzw, r9.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r0.w, r1.z, l(4) + ishr r2.z, r1.z, l(5) + ishr r2.w, r1.z, l(6) + ishl r8.x, r0.z, l(28) + ishl r8.y, r0.w, l(29) + ishl r8.z, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r8.xyz, r8.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.z, l(8) + ishr r0.w, r1.z, l(9) + ishr r2.z, r1.w, l(1) + and r0.y, r0.y, l(1) + ishl r8.x, r0.z, l(1) + ishl r8.y, r0.w, l(2) + ishl r8.z, r2.z, l(4) + and r8.xyz, r8.xyzx, l(2, 4, 16, 0) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r8.z, r0.y + ishr r0.z, r1.w, l(2) + ishr r0.w, r1.w, l(3) + ishr r2.z, r1.w, l(4) + ishl r8.x, r0.z, l(5) + ishl r8.y, r0.w, l(6) + ishl r8.z, r2.z, l(7) + and r8.xyz, r8.xyzx, l(32, 64, 128, 0) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + ishr r0.z, r6.x, l(4) + ishr r0.w, r6.x, l(1) + ishr r2.z, r6.x, l(2) + ishr r2.w, r6.x, l(3) + ishl r8.x, r0.z, l(8) + ishl r8.y, r0.w, l(20) + ishl r8.z, r2.z, l(21) + ishl r8.w, r2.w, l(22) + and r8.xyzw, r8.xyzw, l(256, 0x00100000, 0x00200000, 0x00400000) + iadd r0.y, r0.y, r8.x + ishl r9.x, r5.y, l(9) + ishl r9.y, r5.z, l(29) + ishl r9.z, r5.x, l(1) + ishl r9.w, r5.w, l(7) + and r9.xyzw, r9.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r9.x + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishr r0.zw, r5.yyyz, l(3) + ishr r2.z, r5.z, l(1) + ishr r2.w, r5.z, l(2) + ishl r7.x, r0.z, l(12) + ishl r7.y, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r2.zw, r7.xxxy, l(0, 0, 4096, 0x40000000) + iadd r0.y, r0.y, r2.z + ishl r7.x, r4.x, l(13) + ishl r7.y, r4.y, l(23) + and r4.zw, r7.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r4.z + ishr r2.z, r4.x, l(1) + ishr r4.z, r4.x, l(2) + ishr r6.z, r4.x, l(3) + ishr r6.w, r4.x, l(4) + ishl r7.x, r2.z, l(14) + ishl r7.y, r4.z, l(15) + ishl r7.z, r6.z, l(16) + ishl r7.w, r6.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r6.y, l(18) + ishl r7.y, r6.x, l(19) + and r6.zw, r7.xxxy, l(0, 0, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r6.z + iadd r0.y, r6.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r4.w, r0.y + ishr r2.z, r4.y, l(1) + ishr r4.z, r4.y, l(2) + ishr r4.w, r4.y, l(3) + ishr r6.z, r4.y, l(4) + ishl r7.x, r2.z, l(24) + ishl r7.y, r4.z, l(25) + ishl r7.z, r4.w, l(26) + ishl r7.w, r6.z, l(27) + and r7.xyzw, r7.xyzw, l(0x01000000, 0x02000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishr r2.z, r6.y, l(1) + ishr r4.z, r6.y, l(2) + ishr r4.w, r6.y, l(3) + ishl r7.x, r2.z, l(28) + ishl r7.y, r4.z, l(6) + ishl r7.z, r4.w, l(12) + and r7.xyz, r7.xyzx, l(0x10000000, 64, 4096, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r2.w, r0.y + iadd r3.z, r0.z, r0.y + and r0.y, r0.w, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r9.z, r0.y + ishr r0.z, r5.x, l(1) + ishr r0.w, r5.x, l(2) + ishr r2.z, r5.x, l(3) + ishr r2.w, r5.x, l(4) + ishl r8.x, r0.z, l(2) + ishl r8.y, r0.w, l(3) + ishl r8.z, r2.z, l(4) + ishl r8.w, r2.w, l(5) + and r8.xyzw, r8.xyzw, l(4, 8, 16, 32) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r5.w, l(1) + ishr r0.w, r5.w, l(2) + ishr r2.z, r5.w, l(3) + ishr r2.w, r5.w, l(4) + ishl r8.x, r0.z, l(8) + ishl r8.y, r0.w, l(9) + ishl r8.z, r2.z, l(10) + ishl r8.w, r2.w, l(11) + and r8.xyzw, r8.xyzw, l(256, 512, 1024, 2048) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r7.z, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(2) + if_nz r0.y + ishr r0.yz, r5.yyzy, l(5) + ishr r2.zw, r5.zzzy, l(4) + ishl r7.x, r0.y, l(2) + ishl r7.y, r2.z, l(14) + ishl r7.z, r0.z, l(22) + ishl r7.w, r2.w, l(24) + and r7.xyzw, r7.xyzw, l(4, 0x00004000, 0x00400000, 0x01000000) + iadd r0.y, r7.x, l(1) + ishr r0.z, r6.x, l(4) + ishr r0.w, r6.x, l(5) + ishr r2.z, r6.y, l(1) + ishr r2.w, r6.y, l(2) + ishl r8.x, r0.z, l(3) + ishl r8.y, r0.w, l(4) + ishl r8.z, r2.z, l(13) + ishl r8.w, r2.w, l(23) + and r8.xyzw, r8.xyzw, l(8, 16, 8192, 0x00800000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + ishl r9.x, r1.x, l(5) + ishl r9.y, r1.y, l(15) + ishl r9.z, r1.z, l(25) + ishl r9.w, r1.w, l(3) + and r9.xyzw, r9.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r0.y, r9.x + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r10.x, r0.z, l(6) + ishl r10.y, r0.w, l(7) + ishl r10.z, r2.z, l(8) + ishl r10.w, r2.w, l(9) + and r10.xyzw, r10.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.y, l(1) + ishr r2.w, r1.y, l(2) + ishl r10.x, r0.z, l(10) + ishl r10.y, r0.w, l(11) + ishl r10.z, r2.z, l(16) + ishl r10.w, r2.w, l(17) + and r10.xyzw, r10.xyzw, l(1024, 2048, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + ishl r8.x, r6.y, l(12) + ishl r8.y, r6.x, l(19) + and r0.zw, r8.xxxy, l(0, 0, 4096, 0x00080000) + iadd r0.y, r0.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.z, r1.y, l(3) + ishr r2.z, r1.y, l(4) + ishr r2.w, r1.y, l(5) + ishr r4.z, r1.y, l(6) + ishl r10.x, r0.z, l(18) + ishl r10.y, r2.z, l(19) + ishl r10.z, r2.w, l(20) + ishl r10.w, r4.z, l(21) + and r10.xyzw, r10.xyzw, l(0x00040000, 0x00080000, 0x00100000, 0x00200000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r9.z, r0.y + ishr r0.z, r1.z, l(1) + ishr r2.z, r1.z, l(2) + ishr r2.w, r1.z, l(3) + ishr r4.z, r1.z, l(4) + ishl r7.x, r0.z, l(26) + ishl r7.y, r2.z, l(27) + ishl r7.z, r2.w, l(28) + ishl r7.w, r4.z, l(29) + and r7.xyzw, r7.xyzw, l(0x04000000, 0x08000000, 0x10000000, 0x20000000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishr r0.z, r1.z, l(5) + ishr r2.z, r1.z, l(6) + ishr r2.w, r1.w, l(1) + ishr r4.z, r1.w, l(2) + ishl r7.x, r0.z, l(30) + ishl r0.z, r2.z, l(31) + ishl r7.z, r2.w, l(4) + ishl r7.w, r4.z, l(5) + and r7.xyz, r7.xzwx, l(0x40000000, 16, 32, 0) + iadd r0.y, r0.y, r7.x + iadd r3.x, r0.z, r0.y + ishr r0.y, r6.y, l(3) + ishr r0.z, r6.y, l(5) + ishr r2.z, r6.y, l(4) + ishr r2.w, r6.x, l(1) + and r0.y, r0.y, l(1) + ishl r8.x, r0.z, l(1) + ishl r8.y, r2.z, l(2) + ishl r8.z, r2.w, l(20) + and r8.xyz, r8.xyzx, l(2, 4, 0x00100000, 0) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(3) + ishr r2.z, r1.w, l(4) + ishr r2.w, r1.w, l(5) + ishl r7.x, r0.z, l(6) + ishl r7.y, r2.z, l(7) + ishl r7.z, r2.w, l(8) + and r7.xyz, r7.xyzx, l(64, 128, 256, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + ishr r2.zw, r5.yyyz, l(1) + ishr r0.z, r5.y, l(2) + ishr r4.z, r5.y, l(3) + ishl r9.x, r2.z, l(10) + ishl r9.y, r0.z, l(11) + ishl r9.z, r4.z, l(12) + ishl r9.w, r2.w, l(30) + and r9.xyzw, r9.xyzw, l(1024, 2048, 4096, 0x40000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + ishl r8.x, r4.x, l(13) + ishl r8.y, r4.y, l(23) + and r2.zw, r8.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r2.z + ishr r0.z, r4.x, l(1) + ishr r2.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishr r4.w, r4.x, l(4) + ishl r10.x, r0.z, l(14) + ishl r10.y, r2.z, l(15) + ishl r10.z, r4.z, l(16) + ishl r10.w, r4.w, l(17) + and r10.xyzw, r10.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.z, r4.x, l(5) + ishr r2.z, r4.y, l(1) + ishr r4.z, r4.y, l(2) + ishr r4.w, r4.y, l(3) + ishl r10.x, r0.z, l(18) + ishl r10.y, r2.z, l(24) + ishl r10.z, r4.z, l(25) + ishl r10.w, r4.w, l(26) + and r10.xyzw, r10.xyzw, l(0x00040000, 0x01000000, 0x02000000, 0x04000000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r0.w, r0.y + iadd r0.y, r8.z, r0.y + ishr r0.z, r6.x, l(2) + ishr r0.w, r6.x, l(3) + ishl r8.x, r0.z, l(21) + ishl r8.y, r0.w, l(22) + and r0.zw, r8.xxxy, l(0, 0, 0x00200000, 0x00400000) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r2.w, r0.y + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.z, r4.y, l(4) + ishr r0.w, r4.y, l(5) + ishl r8.x, r0.z, l(27) + ishl r8.y, r0.w, l(28) + and r0.zw, r8.xxxy, l(0, 0, 0x08000000, 0x10000000) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.zw, r5.zzzx, l(2) + ishr r2.z, r5.z, l(3) + ishr r2.w, r5.x, l(1) + ishl r8.x, r0.z, l(31) + ishl r8.y, r2.w, l(2) + ishl r8.z, r0.w, l(3) + iadd r3.z, r0.y, r8.x + and r0.y, r2.z, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + and r0.zw, r8.yyyz, l(0, 0, 4, 8) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + ishr r0.z, r5.x, l(3) + ishr r0.w, r5.x, l(4) + ishr r2.z, r5.x, l(5) + ishr r2.w, r5.w, l(1) + ishl r8.x, r0.z, l(4) + ishl r8.y, r0.w, l(5) + ishl r8.z, r2.z, l(6) + ishl r8.w, r2.w, l(8) + and r8.xyzw, r8.xyzw, l(16, 32, 64, 256) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.w, l(2) + ishr r0.w, r5.w, l(3) + ishr r2.z, r5.w, l(4) + ishr r2.w, r5.w, l(5) + ishl r7.x, r0.z, l(9) + ishl r7.y, r0.w, l(10) + ishl r7.z, r2.z, l(11) + ishl r7.w, r2.w, l(12) + and r7.xyzw, r7.xyzw, l(512, 1024, 2048, 4096) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(3) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(2) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.x, l(8) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(13) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(9) + ishr r0.w, r1.y, l(1) + ishr r2.z, r1.y, l(2) + ishr r2.w, r1.y, l(3) + ishl r8.x, r0.z, l(14) + ishl r8.y, r0.w, l(16) + ishl r8.z, r2.z, l(17) + ishl r8.w, r2.w, l(18) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(4) + ishr r0.w, r1.y, l(5) + ishr r2.z, r1.y, l(6) + ishr r2.w, r1.y, l(7) + ishl r8.x, r0.z, l(19) + ishl r8.y, r0.w, l(20) + ishl r8.z, r2.z, l(21) + ishl r8.w, r2.w, l(22) + and r8.xyzw, r8.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(8) + ishr r0.w, r1.y, l(9) + ishr r2.z, r1.z, l(1) + ishr r2.w, r1.z, l(2) + ishl r8.x, r0.z, l(23) + ishl r8.y, r0.w, l(24) + ishl r8.z, r2.z, l(26) + ishl r8.w, r2.w, l(27) + and r8.xyzw, r8.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r0.w, r1.z, l(4) + ishr r2.z, r1.z, l(5) + ishr r2.w, r1.z, l(6) + ishl r7.x, r0.z, l(28) + ishl r7.y, r0.w, l(29) + ishl r7.z, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r7.xyz, r7.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.z, l(8) + ishr r0.w, r1.z, l(9) + ishr r2.z, r1.w, l(1) + and r0.y, r0.y, l(1) + ishl r7.x, r0.z, l(1) + ishl r7.y, r0.w, l(2) + ishl r7.z, r2.z, l(4) + and r7.xyz, r7.xyzx, l(2, 4, 16, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(2) + ishr r0.w, r1.w, l(3) + ishr r2.z, r1.w, l(4) + ishr r2.w, r1.x, l(10) + ishl r7.x, r0.z, l(5) + ishl r7.y, r0.w, l(6) + ishl r7.z, r2.z, l(7) + ishl r7.w, r2.w, l(8) + and r7.xyzw, r7.xyzw, l(32, 64, 128, 256) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + ishr r0.zw, r5.yyyz, l(1) + ishr r2.z, r5.y, l(2) + ishr r2.w, r5.y, l(3) + ishl r8.x, r0.z, l(10) + ishl r8.y, r2.z, l(11) + ishl r8.z, r2.w, l(12) + ishl r8.w, r0.w, l(30) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 0x40000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + ishl r8.x, r4.x, l(13) + ishl r8.y, r4.y, l(23) + and r0.zw, r8.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.z, r0.y + ishr r2.zw, r4.xxxy, l(1) + ishr r0.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishl r9.x, r2.z, l(14) + ishl r9.y, r0.z, l(15) + ishl r9.z, r4.z, l(16) + ishl r9.w, r2.w, l(24) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x01000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + ishr r2.zw, r1.yyyz, l(10) + ishl r8.x, r2.z, l(17) + ishl r8.y, r2.w, l(27) + and r2.zw, r8.xxxy, l(0, 0, 0x00020000, 0x08000000) + iadd r0.y, r0.y, r2.z + ishl r8.x, r6.y, l(18) + ishl r8.y, r6.x, l(19) + and r4.zw, r8.xxxy, l(0, 0, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r4.z + iadd r0.y, r4.w, r0.y + ishr r4.zw, r6.xxxy, l(1) + ishr r0.z, r6.x, l(2) + ishr r2.z, r6.x, l(3) + ishl r10.x, r4.z, l(20) + ishl r10.y, r0.z, l(21) + ishl r10.z, r2.z, l(22) + ishl r10.w, r4.w, l(28) + and r10.xyzw, r10.xyzw, l(0x00100000, 0x00200000, 0x00400000, 0x10000000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r4.y, l(2) + ishr r0.w, r4.y, l(3) + ishl r8.x, r0.z, l(25) + ishl r8.y, r0.w, l(26) + and r0.zw, r8.xxxy, l(0, 0, 0x02000000, 0x04000000) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r2.w, r0.y + iadd r0.y, r10.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.zw, r5.zzzx, l(2) + ishr r2.z, r5.z, l(3) + ishr r2.w, r5.x, l(1) + ishl r8.x, r0.z, l(31) + ishl r8.y, r2.w, l(2) + ishl r8.z, r0.w, l(3) + iadd r3.z, r0.y, r8.x + and r0.y, r2.z, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + and r0.zw, r8.yyyz, l(0, 0, 4, 8) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + ishr r0.z, r5.x, l(3) + ishr r0.w, r5.x, l(4) + ishr r2.z, r5.w, l(1) + ishr r2.w, r5.w, l(2) + ishl r8.x, r0.z, l(4) + ishl r8.y, r0.w, l(5) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(16, 32, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + ishr r0.z, r6.y, l(2) + ishr r0.w, r6.y, l(3) + ishl r7.x, r0.z, l(6) + ishl r7.y, r0.w, l(12) + and r0.zw, r7.xxxy, l(0, 0, 64, 4096) + iadd r0.y, r0.z, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.w, l(3) + ishr r2.z, r5.w, l(4) + ishl r7.x, r0.z, l(10) + ishl r7.y, r2.z, l(11) + and r2.zw, r7.xxxy, l(0, 0, 1024, 2048) + iadd r0.y, r0.y, r2.z + iadd r0.y, r2.w, r0.y + iadd r0.y, r0.w, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(4) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(6) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.x, l(8) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(13) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(9) + ishr r0.w, r1.y, l(1) + ishr r2.z, r1.y, l(2) + ishr r2.w, r1.y, l(3) + ishl r8.x, r0.z, l(14) + ishl r8.y, r0.w, l(16) + ishl r8.z, r2.z, l(17) + ishl r8.w, r2.w, l(18) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(4) + ishr r0.w, r1.y, l(5) + ishr r2.z, r1.y, l(6) + ishr r2.w, r1.y, l(7) + ishl r8.x, r0.z, l(19) + ishl r8.y, r0.w, l(20) + ishl r8.z, r2.z, l(21) + ishl r8.w, r2.w, l(22) + and r8.xyzw, r8.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(8) + ishr r0.w, r1.y, l(9) + ishr r2.z, r1.z, l(1) + ishr r2.w, r1.z, l(2) + ishl r8.x, r0.z, l(23) + ishl r8.y, r0.w, l(24) + ishl r8.z, r2.z, l(26) + ishl r8.w, r2.w, l(27) + and r8.xyzw, r8.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r0.w, r1.z, l(4) + ishr r2.z, r1.z, l(5) + ishr r2.w, r1.z, l(6) + ishl r7.x, r0.z, l(28) + ishl r7.y, r0.w, l(29) + ishl r7.z, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r7.xyz, r7.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.z, l(8) + ishr r0.w, r1.z, l(9) + ishr r2.z, r1.w, l(1) + and r0.y, r0.y, l(1) + ishl r7.x, r0.z, l(1) + ishl r7.y, r0.w, l(2) + ishl r7.z, r2.z, l(4) + and r7.xyz, r7.xyzx, l(2, 4, 16, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(2) + ishr r0.w, r1.w, l(3) + ishr r2.zw, r1.xxxy, l(10) + ishl r7.x, r0.z, l(5) + ishl r7.y, r0.w, l(6) + ishl r7.z, r2.z, l(7) + ishl r7.w, r2.w, l(18) + and r7.xyzw, r7.xyzw, l(32, 64, 128, 0x00040000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r6.x, l(4) + ishr r0.w, r6.x, l(1) + ishr r2.z, r6.x, l(2) + ishr r2.w, r6.x, l(3) + ishl r8.x, r0.z, l(8) + ishl r8.y, r0.w, l(20) + ishl r8.z, r2.z, l(21) + ishl r8.w, r2.w, l(22) + and r8.xyzw, r8.xyzw, l(256, 0x00100000, 0x00200000, 0x00400000) + iadd r0.y, r0.y, r8.x + ishl r9.x, r5.y, l(9) + ishl r9.y, r5.z, l(29) + ishl r9.z, r5.x, l(1) + ishl r9.w, r5.w, l(7) + and r9.xyzw, r9.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r9.x + ishr r0.zw, r5.yyyz, l(1) + ishr r2.z, r5.y, l(2) + ishr r2.w, r5.y, l(3) + ishl r10.x, r0.z, l(10) + ishl r10.y, r2.z, l(11) + ishl r10.z, r2.w, l(12) + ishl r10.w, r0.w, l(30) + and r10.xyzw, r10.xyzw, l(1024, 2048, 4096, 0x40000000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + ishl r7.x, r4.x, l(13) + ishl r7.y, r4.y, l(23) + and r0.zw, r7.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.z, r0.y + ishr r0.z, r4.x, l(1) + ishr r2.z, r4.x, l(2) + ishr r2.w, r4.x, l(3) + ishr r4.z, r4.x, l(4) + ishl r11.x, r0.z, l(14) + ishl r11.y, r2.z, l(15) + ishl r11.z, r2.w, l(16) + ishl r11.w, r4.z, l(17) + and r11.xyzw, r11.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r11.x + iadd r0.y, r11.y, r0.y + iadd r0.y, r11.z, r0.y + iadd r0.y, r11.w, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r6.x, l(19) + ishl r7.y, r6.y, l(5) + and r2.zw, r7.xxxy, l(0, 0, 0x00080000, 32) + iadd r0.y, r0.y, r2.z + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r0.w, r0.y + ishr r0.z, r4.y, l(1) + ishr r0.w, r4.y, l(2) + ishr r2.z, r4.y, l(3) + ishl r7.x, r0.z, l(24) + ishl r7.y, r0.w, l(25) + ishl r7.z, r2.z, l(26) + and r7.xyz, r7.xyzx, l(0x01000000, 0x02000000, 0x04000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.z, l(10) + ishl r0.z, r0.z, l(27) + and r0.z, r0.z, l(0x08000000) + iadd r0.y, r0.z, r0.y + ishr r0.z, r6.y, l(1) + ishr r0.w, r6.y, l(2) + ishr r2.z, r6.y, l(3) + ishl r7.x, r0.z, l(28) + ishl r7.y, r0.w, l(6) + ishl r7.z, r2.z, l(12) + and r7.xyz, r7.xyzx, l(0x10000000, 64, 4096, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.zw, r5.zzzx, l(2) + ishr r2.z, r5.z, l(3) + ishr r4.z, r5.x, l(1) + ishl r8.x, r0.z, l(31) + ishl r8.y, r4.z, l(2) + ishl r8.z, r0.w, l(3) + iadd r3.z, r0.y, r8.x + and r0.y, r2.z, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r9.z, r0.y + and r0.zw, r8.yyyz, l(0, 0, 4, 8) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + ishr r0.zw, r5.xxxw, l(3) + ishr r2.z, r5.w, l(1) + ishr r4.z, r5.w, l(2) + ishl r8.x, r0.z, l(4) + ishl r8.y, r2.z, l(8) + ishl r8.z, r4.z, l(9) + ishl r8.w, r0.w, l(10) + and r8.xyzw, r8.xyzw, l(16, 256, 512, 1024) + iadd r0.y, r0.y, r8.x + iadd r0.y, r2.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.y, l(4) + ishl r0.z, r0.z, l(11) + and r0.z, r0.z, l(2048) + iadd r0.y, r0.z, r0.y + iadd r0.y, r7.z, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(5) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(10) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.x, l(8) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(13) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(9) + ishr r0.w, r1.y, l(1) + ishr r2.z, r1.y, l(2) + ishr r2.w, r1.y, l(3) + ishl r8.x, r0.z, l(14) + ishl r8.y, r0.w, l(16) + ishl r8.z, r2.z, l(17) + ishl r8.w, r2.w, l(18) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x00010000, 0x00020000, 0x00040000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(4) + ishr r0.w, r1.y, l(5) + ishr r2.z, r1.y, l(6) + ishr r2.w, r1.y, l(7) + ishl r8.x, r0.z, l(19) + ishl r8.y, r0.w, l(20) + ishl r8.z, r2.z, l(21) + ishl r8.w, r2.w, l(22) + and r8.xyzw, r8.xyzw, l(0x00080000, 0x00100000, 0x00200000, 0x00400000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(8) + ishr r0.w, r1.y, l(9) + ishr r2.z, r1.z, l(1) + ishr r2.w, r1.z, l(2) + ishl r8.x, r0.z, l(23) + ishl r8.y, r0.w, l(24) + ishl r8.z, r2.z, l(26) + ishl r8.w, r2.w, l(27) + and r8.xyzw, r8.xyzw, l(0x00800000, 0x01000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r0.w, r1.z, l(4) + ishr r2.z, r1.z, l(5) + ishr r2.w, r1.z, l(6) + ishl r7.x, r0.z, l(28) + ishl r7.y, r0.w, l(29) + ishl r7.z, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r7.xyz, r7.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.z, l(8) + ishr r0.w, r1.z, l(9) + ishr r2.z, r1.w, l(1) + and r0.y, r0.y, l(1) + ishl r7.x, r0.z, l(1) + ishl r7.y, r0.w, l(2) + ishl r7.z, r2.z, l(4) + and r7.xyz, r7.xyzx, l(2, 4, 16, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(2) + ishr r0.w, r1.w, l(3) + ishr r2.zw, r1.xxxy, l(10) + ishl r7.x, r0.z, l(5) + ishl r7.y, r0.w, l(6) + ishl r7.z, r2.z, l(7) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(32, 64, 128, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r5.z, l(4) + ishr r0.w, r5.y, l(1) + ishr r2.z, r5.y, l(2) + ishr r2.w, r5.y, l(3) + ishl r8.x, r0.z, l(8) + ishl r8.y, r0.w, l(10) + ishl r8.z, r2.z, l(11) + ishl r8.w, r2.w, l(12) + and r8.xyzw, r8.xyzw, l(256, 1024, 2048, 4096) + iadd r0.y, r0.y, r8.x + ishl r9.x, r5.y, l(9) + ishl r9.y, r5.z, l(29) + ishl r9.z, r5.x, l(1) + ishl r9.w, r5.w, l(7) + and r9.xyzw, r9.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r9.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishl r7.x, r4.x, l(13) + ishl r7.y, r4.y, l(23) + and r0.zw, r7.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.z, r0.y + ishr r2.zw, r4.xxxy, l(1) + ishr r0.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishl r8.x, r2.z, l(14) + ishl r8.y, r0.z, l(15) + ishl r8.z, r4.z, l(16) + ishl r8.w, r2.w, l(24) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x01000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r6.y, l(18) + ishl r7.y, r6.x, l(19) + and r2.zw, r7.xxxy, l(0, 0, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r2.z + iadd r0.y, r2.w, r0.y + ishr r2.zw, r6.xxxy, l(1) + ishr r0.z, r6.x, l(2) + ishr r4.z, r6.x, l(3) + ishl r7.x, r2.z, l(20) + ishl r7.y, r0.z, l(21) + ishl r7.z, r4.z, l(22) + ishl r7.w, r2.w, l(5) + and r7.xyzw, r7.xyzw, l(0x00100000, 0x00200000, 0x00400000, 32) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r4.y, l(2) + ishr r0.w, r4.y, l(3) + ishr r2.z, r4.y, l(4) + ishl r7.x, r0.z, l(25) + ishl r7.y, r0.w, l(26) + ishl r7.z, r2.z, l(27) + and r7.xyz, r7.xyzx, l(0x02000000, 0x04000000, 0x08000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.z, l(10) + ishl r0.z, r0.z, l(28) + and r0.z, r0.z, l(0x10000000) + iadd r0.y, r0.z, r0.y + iadd r0.y, r9.y, r0.y + ishr r0.zw, r5.zzzx, l(1) + ishr r2.z, r5.z, l(2) + ishr r2.w, r5.z, l(3) + ishl r7.x, r0.z, l(30) + ishl r0.z, r2.z, l(31) + ishl r7.z, r0.w, l(2) + and r4.zw, r7.xxxz, l(0, 0, 0x40000000, 4) + iadd r0.y, r0.y, r4.z + iadd r3.z, r0.z, r0.y + and r0.y, r2.w, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r9.z, r0.y + iadd r0.y, r4.w, r0.y + ishr r0.zw, r5.xxxw, l(2) + ishr r2.z, r5.x, l(3) + ishr r2.w, r5.w, l(1) + ishl r8.x, r0.z, l(3) + ishl r8.y, r2.z, l(4) + ishl r8.z, r2.w, l(8) + ishl r8.w, r0.w, l(9) + and r8.xyzw, r8.xyzw, l(8, 16, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.w, r0.y + ishr r0.z, r6.y, l(2) + ishr r0.w, r6.y, l(4) + ishr r2.z, r6.y, l(3) + ishl r7.x, r0.z, l(6) + ishl r7.y, r0.w, l(11) + ishl r7.z, r2.z, l(12) + and r7.xyz, r7.xyzx, l(64, 2048, 4096, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r9.w, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.w, l(3) + ishl r0.z, r0.z, l(10) + and r0.z, r0.z, l(1024) + iadd r0.y, r0.z, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(6) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(14) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.x, l(8) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(13) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 8192) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.zw, r5.zzzy, l(4) + ishr r2.z, r5.y, l(1) + ishr r2.w, r5.y, l(2) + ishl r8.x, r0.z, l(14) + ishl r8.y, r0.w, l(24) + ishl r8.z, r2.z, l(10) + ishl r8.w, r2.w, l(11) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x01000000, 1024, 2048) + iadd r0.y, r0.y, r8.x + iadd r0.y, r7.y, r0.y + ishr r0.z, r1.y, l(1) + ishr r0.w, r1.y, l(2) + ishr r2.z, r1.y, l(3) + ishr r2.w, r1.y, l(4) + ishl r9.x, r0.z, l(16) + ishl r9.y, r0.w, l(17) + ishl r9.z, r2.z, l(18) + ishl r9.w, r2.w, l(19) + and r9.xyzw, r9.xyzw, l(0x00010000, 0x00020000, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.y, l(5) + ishr r0.w, r1.y, l(6) + ishr r2.z, r1.y, l(7) + ishr r2.w, r1.y, l(8) + ishl r9.x, r0.z, l(20) + ishl r9.y, r0.w, l(21) + ishl r9.z, r2.z, l(22) + ishl r9.w, r2.w, l(23) + and r9.xyzw, r9.xyzw, l(0x00100000, 0x00200000, 0x00400000, 0x00800000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.z, l(1) + ishr r0.w, r1.z, l(2) + ishr r2.z, r1.z, l(3) + ishr r2.w, r1.z, l(4) + ishl r9.x, r0.z, l(26) + ishl r9.y, r0.w, l(27) + ishl r9.z, r2.z, l(28) + ishl r9.w, r2.w, l(29) + and r9.xyzw, r9.xyzw, l(0x04000000, 0x08000000, 0x10000000, 0x20000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r1.z, l(5) + ishr r0.w, r1.z, l(6) + ishr r2.z, r1.z, l(7) + ishr r2.w, r1.z, l(8) + ishl r7.x, r0.z, l(30) + ishl r0.z, r0.w, l(31) + ishl r7.z, r2.w, l(1) + and r4.zw, r7.xxxz, l(0, 0, 0x40000000, 2) + iadd r0.y, r0.y, r4.z + iadd r3.x, r0.z, r0.y + and r0.y, r2.z, l(1) + iadd r0.y, r4.w, r0.y + ishr r0.zw, r6.yyyx, l(4) + ishr r2.z, r6.x, l(1) + ishr r2.w, r6.x, l(2) + ishl r9.x, r0.z, l(2) + ishl r9.y, r0.w, l(8) + ishl r9.z, r2.z, l(20) + ishl r9.w, r2.w, l(21) + and r9.xyzw, r9.xyzw, l(4, 256, 0x00100000, 0x00200000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r7.w, r0.y + ishr r0.z, r1.w, l(1) + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + ishr r2.w, r1.w, l(4) + ishl r7.x, r0.z, l(4) + ishl r7.y, r0.w, l(5) + ishl r7.z, r2.z, l(6) + ishl r7.w, r2.w, l(7) + and r7.xyzw, r7.xyzw, l(16, 32, 64, 128) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r9.y, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.zw, r5.yyyz, l(3) + ishr r2.z, r5.z, l(1) + ishr r2.w, r5.z, l(2) + ishl r8.x, r0.z, l(12) + ishl r8.y, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r2.zw, r8.xxxy, l(0, 0, 4096, 0x40000000) + iadd r0.y, r0.y, r2.z + ishl r8.x, r4.x, l(13) + ishl r8.y, r4.y, l(23) + and r4.zw, r8.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r4.z + ishr r2.z, r4.x, l(1) + ishr r4.z, r4.x, l(2) + ishr r6.z, r4.x, l(3) + ishr r6.w, r4.x, l(4) + ishl r8.x, r2.z, l(14) + ishl r8.y, r4.z, l(15) + ishl r8.z, r6.z, l(16) + ishl r8.w, r6.w, l(17) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishl r8.x, r6.y, l(18) + ishl r8.y, r6.x, l(19) + and r6.zw, r8.xxxy, l(0, 0, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r6.z + iadd r0.y, r6.w, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r6.zw, r6.xxxy, l(3) + ishr r2.z, r6.y, l(1) + ishr r4.z, r6.y, l(2) + ishl r8.x, r6.z, l(22) + ishl r8.y, r2.z, l(28) + ishl r8.z, r4.z, l(6) + ishl r8.w, r6.w, l(12) + and r8.xyzw, r8.xyzw, l(0x00400000, 0x10000000, 64, 4096) + iadd r0.y, r0.y, r8.x + iadd r0.y, r4.w, r0.y + ishr r2.z, r4.y, l(1) + ishr r4.z, r4.y, l(2) + ishr r4.w, r4.y, l(3) + ishr r6.z, r4.y, l(4) + ishl r9.x, r2.z, l(24) + ishl r9.y, r4.z, l(25) + ishl r9.z, r4.w, l(26) + ishl r9.w, r6.z, l(27) + and r9.xyzw, r9.xyzw, l(0x01000000, 0x02000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r2.w, r0.y + iadd r3.z, r0.z, r0.y + and r0.y, r0.w, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + ishr r0.z, r5.x, l(1) + ishr r0.w, r5.x, l(2) + ishr r2.z, r5.x, l(3) + ishr r2.w, r5.x, l(4) + ishl r9.x, r0.z, l(2) + ishl r9.y, r0.w, l(3) + ishl r9.z, r2.z, l(4) + ishl r9.w, r2.w, l(5) + and r9.xyzw, r9.xyzw, l(4, 8, 16, 32) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r7.w, r0.y + ishr r0.z, r5.w, l(1) + ishr r0.w, r5.w, l(2) + ishr r2.z, r5.w, l(3) + ishr r2.w, r5.w, l(4) + ishl r7.x, r0.z, l(8) + ishl r7.y, r0.w, l(9) + ishl r7.z, r2.z, l(10) + ishl r7.w, r2.w, l(11) + and r7.xyzw, r7.xyzw, l(256, 512, 1024, 2048) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.w, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(7) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(18) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.y, l(1) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(16) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 0x00010000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + ishr r0.zw, r6.xxxy, l(4) + ishr r2.z, r6.y, l(2) + ishr r2.w, r6.y, l(3) + ishl r9.x, r0.z, l(13) + ishl r9.y, r2.z, l(23) + ishl r9.z, r2.w, l(1) + ishl r9.w, r0.w, l(2) + and r9.xyzw, r9.xyzw, l(8192, 0x00800000, 2, 4) + iadd r0.y, r0.y, r9.x + ishr r0.zw, r5.zzzy, l(4) + ishr r2.z, r5.y, l(1) + ishr r2.w, r5.y, l(2) + ishl r10.x, r0.z, l(14) + ishl r10.y, r0.w, l(24) + ishl r10.z, r2.z, l(10) + ishl r10.w, r2.w, l(11) + and r10.xyzw, r10.xyzw, l(0x00004000, 0x01000000, 1024, 2048) + iadd r0.y, r0.y, r10.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(2) + ishr r0.w, r1.y, l(3) + ishr r2.z, r1.y, l(4) + ishr r2.w, r1.y, l(5) + ishl r8.x, r0.z, l(17) + ishl r8.y, r0.w, l(18) + ishl r8.z, r2.z, l(19) + ishl r8.w, r2.w, l(20) + and r8.xyzw, r8.xyzw, l(0x00020000, 0x00040000, 0x00080000, 0x00100000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(6) + ishr r0.w, r1.y, l(7) + ishr r2.z, r1.z, l(1) + ishr r2.w, r1.z, l(2) + ishl r8.x, r0.z, l(21) + ishl r8.y, r0.w, l(22) + ishl r8.z, r2.z, l(26) + ishl r8.w, r2.w, l(27) + and r8.xyzw, r8.xyzw, l(0x00200000, 0x00400000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r10.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r0.w, r1.z, l(4) + ishr r2.z, r1.z, l(5) + ishr r2.w, r1.z, l(6) + ishl r7.x, r0.z, l(28) + ishl r7.y, r0.w, l(29) + ishl r7.z, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r7.xyz, r7.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.w, l(1) + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + and r0.y, r0.y, l(1) + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r0.z, l(4) + ishl r7.y, r0.w, l(5) + ishl r7.z, r2.z, l(6) + and r7.xyz, r7.xyzx, l(16, 32, 64, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(4) + ishr r0.w, r1.w, l(5) + ishl r7.x, r0.z, l(7) + ishl r7.y, r0.w, l(8) + and r0.zw, r7.xxxy, l(0, 0, 128, 256) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.zw, r5.yyyz, l(3) + ishr r2.z, r5.z, l(1) + ishr r2.w, r5.z, l(2) + ishl r8.x, r0.z, l(12) + ishl r8.y, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r2.zw, r8.xxxy, l(0, 0, 4096, 0x40000000) + iadd r0.y, r0.y, r2.z + ishl r8.x, r4.x, l(13) + ishl r8.y, r4.y, l(23) + and r4.zw, r8.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r4.z + ishr r2.z, r4.x, l(1) + ishr r4.z, r4.x, l(2) + ishr r6.z, r4.x, l(3) + ishr r6.w, r4.x, l(4) + ishl r8.x, r2.z, l(14) + ishl r8.y, r4.z, l(15) + ishl r8.z, r6.z, l(16) + ishl r8.w, r6.w, l(17) + and r8.xyzw, r8.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishl r8.x, r6.y, l(18) + ishl r8.y, r6.x, l(19) + and r6.zw, r8.xxxy, l(0, 0, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r6.z + iadd r0.y, r6.w, r0.y + ishr r6.zw, r6.xxxy, l(1) + ishr r2.z, r6.x, l(2) + ishr r4.z, r6.x, l(3) + ishl r8.x, r6.z, l(20) + ishl r8.y, r2.z, l(21) + ishl r8.z, r4.z, l(22) + ishl r8.w, r6.w, l(28) + and r8.xyzw, r8.xyzw, l(0x00100000, 0x00200000, 0x00400000, 0x10000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r4.w, r0.y + ishr r2.z, r4.y, l(1) + ishr r4.z, r4.y, l(2) + ishr r4.w, r4.y, l(3) + ishr r6.z, r4.y, l(4) + ishl r9.x, r2.z, l(24) + ishl r9.y, r4.z, l(25) + ishl r9.z, r4.w, l(26) + ishl r9.w, r6.z, l(27) + and r9.xyzw, r9.xyzw, l(0x01000000, 0x02000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r8.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r2.w, r0.y + iadd r3.z, r0.z, r0.y + and r0.y, r0.w, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + ishr r0.z, r5.x, l(1) + ishr r0.w, r5.x, l(2) + ishr r2.z, r5.x, l(3) + ishr r2.w, r5.x, l(4) + ishl r8.x, r0.z, l(2) + ishl r8.y, r0.w, l(3) + ishl r8.z, r2.z, l(4) + ishl r8.w, r2.w, l(5) + and r8.xyzw, r8.xyzw, l(4, 8, 16, 32) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.x, l(5) + ishr r0.w, r5.w, l(1) + ishr r2.z, r5.w, l(2) + ishr r2.w, r5.w, l(3) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(8) + ishl r8.z, r2.z, l(9) + ishl r8.w, r2.w, l(10) + and r8.xyzw, r8.xyzw, l(64, 256, 512, 1024) + iadd r0.y, r0.y, r8.x + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.w, l(4) + ishr r0.w, r5.w, l(5) + ishl r7.x, r0.z, l(11) + ishl r7.y, r0.w, l(12) + and r0.zw, r7.xxxy, l(0, 0, 2048, 4096) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(8) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(22) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.y, l(1) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(16) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 0x00010000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + ishl r8.x, r6.y, l(13) + ishl r8.y, r6.x, l(19) + and r0.zw, r8.xxxy, l(0, 0, 8192, 0x00080000) + iadd r0.y, r0.z, r0.y + ishr r2.zw, r5.zzzy, l(4) + ishr r0.z, r5.y, l(5) + ishr r4.z, r5.y, l(1) + ishl r9.x, r2.z, l(14) + ishl r9.y, r0.z, l(23) + ishl r9.z, r2.w, l(24) + ishl r9.w, r4.z, l(10) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00800000, 0x01000000, 1024) + iadd r0.y, r0.y, r9.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(2) + ishr r2.z, r1.y, l(3) + ishr r2.w, r1.y, l(4) + ishr r4.z, r1.y, l(5) + ishl r8.x, r0.z, l(17) + ishl r8.y, r2.z, l(18) + ishl r8.z, r2.w, l(19) + ishl r8.w, r4.z, l(20) + and r8.xyzw, r8.xyzw, l(0x00020000, 0x00040000, 0x00080000, 0x00100000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(6) + ishr r2.z, r1.y, l(7) + ishr r2.w, r1.z, l(1) + ishr r4.z, r1.z, l(2) + ishl r8.x, r0.z, l(21) + ishl r8.y, r2.z, l(22) + ishl r8.z, r2.w, l(26) + ishl r8.w, r4.z, l(27) + and r8.xyzw, r8.xyzw, l(0x00200000, 0x00400000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r2.z, r1.z, l(4) + ishr r2.w, r1.z, l(5) + ishr r4.z, r1.z, l(6) + ishl r7.x, r0.z, l(28) + ishl r7.y, r2.z, l(29) + ishl r7.z, r2.w, l(30) + ishl r0.z, r4.z, l(31) + and r7.xyz, r7.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.w, l(1) + ishr r2.z, r1.w, l(2) + ishr r2.w, r1.w, l(3) + and r0.y, r0.y, l(1) + ishr r4.z, r6.x, l(5) + ishr r6.zw, r6.yyyx, l(4) + ishr r4.w, r6.x, l(1) + ishl r8.x, r4.z, l(1) + ishl r8.y, r6.z, l(2) + ishl r8.z, r6.w, l(8) + ishl r8.w, r4.w, l(20) + and r8.xyzw, r8.xyzw, l(2, 4, 256, 0x00100000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r0.z, l(4) + ishl r7.y, r2.z, l(5) + ishl r7.z, r2.w, l(6) + and r7.xyz, r7.xyzx, l(16, 32, 64, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(4) + ishl r0.z, r0.z, l(7) + and r0.z, r0.z, l(128) + iadd r0.y, r0.z, r0.y + iadd r0.y, r8.z, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + iadd r0.y, r9.w, r0.y + ishr r2.zw, r5.yyyz, l(2) + ishr r0.z, r5.y, l(3) + ishr r4.z, r5.z, l(1) + ishl r8.x, r2.z, l(11) + ishl r8.y, r0.z, l(12) + ishl r8.z, r4.z, l(30) + ishl r0.z, r2.w, l(31) + and r8.xyz, r8.xyzx, l(2048, 4096, 0x40000000, 0) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + ishl r8.x, r4.x, l(13) + ishl r8.y, r4.y, l(23) + and r2.zw, r8.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r2.z + ishr r2.z, r4.x, l(1) + ishr r4.z, r4.x, l(2) + ishr r4.w, r4.x, l(3) + ishr r6.z, r4.x, l(4) + ishl r9.x, r2.z, l(14) + ishl r9.y, r4.z, l(15) + ishl r9.z, r4.w, l(16) + ishl r9.w, r6.z, l(17) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r2.z, r4.x, l(5) + ishr r4.z, r4.y, l(1) + ishr r4.w, r4.y, l(2) + ishr r6.z, r4.y, l(3) + ishl r9.x, r2.z, l(18) + ishl r9.y, r4.z, l(24) + ishl r9.z, r4.w, l(25) + ishl r9.w, r6.z, l(26) + and r9.xyzw, r9.xyzw, l(0x00040000, 0x01000000, 0x02000000, 0x04000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r0.w, r0.y + iadd r0.y, r8.w, r0.y + ishr r4.zw, r6.xxxy, l(2) + ishr r0.w, r6.x, l(3) + ishr r2.z, r6.y, l(1) + ishl r10.x, r4.z, l(21) + ishl r10.y, r0.w, l(22) + ishl r10.z, r2.z, l(28) + ishl r10.w, r4.w, l(6) + and r10.xyzw, r10.xyzw, l(0x00200000, 0x00400000, 0x10000000, 64) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r2.w, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.w, r4.y, l(4) + ishl r0.w, r0.w, l(27) + and r0.w, r0.w, l(0x08000000) + iadd r0.y, r0.w, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r3.z, r0.z, r0.y + ishr r0.yz, r5.zzxz, l(3) + ishr r0.w, r5.x, l(1) + ishr r2.z, r5.x, l(2) + and r0.y, r0.y, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + ishl r7.x, r0.w, l(2) + ishl r7.y, r2.z, l(3) + ishl r7.z, r0.z, l(4) + and r7.xyz, r7.xyzx, l(4, 8, 16, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r5.x, l(4) + ishr r0.w, r5.w, l(1) + ishr r2.z, r5.w, l(2) + ishr r2.w, r5.w, l(3) + ishl r8.x, r0.z, l(5) + ishl r8.y, r0.w, l(8) + ishl r8.z, r2.z, l(9) + ishl r8.w, r2.w, l(10) + and r8.xyzw, r8.xyzw, l(32, 256, 512, 1024) + iadd r0.y, r0.y, r8.x + iadd r0.y, r10.w, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.w, l(4) + ishl r0.z, r0.z, l(11) + and r0.z, r0.z, l(2048) + iadd r0.y, r0.z, r0.y + ishr r0.z, r6.y, l(3) + ishl r0.z, r0.z, l(12) + and r0.z, r0.z, l(4096) + iadd r0.y, r0.z, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(9) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(26) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.z, r1.x, l(3) + ishr r2.w, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.z, l(8) + ishl r8.w, r2.w, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.x, l(6) + ishr r2.z, r1.x, l(7) + ishr r2.w, r1.y, l(1) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(11) + ishl r8.z, r2.z, l(12) + ishl r8.w, r2.w, l(16) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 0x00010000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + ishr r0.z, r6.y, l(1) + ishr r0.w, r6.y, l(5) + ishr r2.zw, r6.yyyx, l(4) + ishl r9.x, r0.z, l(13) + ishl r9.y, r0.w, l(1) + ishl r9.z, r2.z, l(2) + ishl r9.w, r2.w, l(8) + and r9.xyzw, r9.xyzw, l(8192, 2, 4, 256) + iadd r0.y, r0.y, r9.x + ishr r0.zw, r5.zzzy, l(4) + ishr r2.z, r5.z, l(5) + ishr r2.w, r5.y, l(1) + ishl r10.x, r0.z, l(14) + ishl r10.y, r2.z, l(23) + ishl r10.z, r0.w, l(24) + ishl r10.w, r2.w, l(10) + and r10.xyzw, r10.xyzw, l(0x00004000, 0x00800000, 0x01000000, 1024) + iadd r0.y, r0.y, r10.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(2) + ishr r0.w, r1.y, l(3) + ishr r2.z, r1.y, l(4) + ishr r2.w, r1.y, l(5) + ishl r8.x, r0.z, l(17) + ishl r8.y, r0.w, l(18) + ishl r8.z, r2.z, l(19) + ishl r8.w, r2.w, l(20) + and r8.xyzw, r8.xyzw, l(0x00020000, 0x00040000, 0x00080000, 0x00100000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.y, l(6) + ishr r0.w, r1.y, l(7) + ishr r2.z, r1.z, l(1) + ishr r2.w, r1.z, l(2) + ishl r8.x, r0.z, l(21) + ishl r8.y, r0.w, l(22) + ishl r8.z, r2.z, l(26) + ishl r8.w, r2.w, l(27) + and r8.xyzw, r8.xyzw, l(0x00200000, 0x00400000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.z, l(3) + ishr r0.w, r1.z, l(4) + ishr r2.z, r1.z, l(5) + ishr r2.w, r1.z, l(6) + ishl r7.x, r0.z, l(28) + ishl r7.y, r0.w, l(29) + ishl r7.z, r2.z, l(30) + ishl r0.z, r2.w, l(31) + and r7.xyz, r7.xyzx, l(0x10000000, 0x20000000, 0x40000000, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r1.z, l(7) + ishr r0.z, r1.w, l(1) + ishr r0.w, r1.w, l(2) + ishr r2.z, r1.w, l(3) + and r0.y, r0.y, l(1) + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r0.z, l(4) + ishl r7.y, r0.w, l(5) + ishl r7.z, r2.z, l(6) + and r7.xyz, r7.xyzx, l(16, 32, 64, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r1.w, l(4) + ishl r0.z, r0.z, l(7) + and r0.z, r0.z, l(128) + iadd r0.y, r0.z, r0.y + iadd r0.y, r9.w, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + iadd r0.y, r10.w, r0.y + ishr r0.zw, r5.yyyz, l(2) + ishr r2.z, r5.y, l(3) + ishr r2.w, r5.z, l(1) + ishl r8.x, r0.z, l(11) + ishl r8.y, r2.z, l(12) + ishl r8.z, r2.w, l(30) + ishl r0.z, r0.w, l(31) + and r8.xyz, r8.xyzx, l(2048, 4096, 0x40000000, 0) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + ishl r8.x, r4.x, l(13) + ishl r8.y, r4.y, l(23) + and r2.zw, r8.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r2.z + ishr r0.w, r4.x, l(1) + ishr r2.z, r4.x, l(2) + ishr r4.z, r4.x, l(3) + ishr r4.w, r4.x, l(4) + ishl r9.x, r0.w, l(14) + ishl r9.y, r2.z, l(15) + ishl r9.z, r4.z, l(16) + ishl r9.w, r4.w, l(17) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishl r8.x, r6.y, l(18) + ishl r8.y, r6.x, l(19) + and r4.zw, r8.xxxy, l(0, 0, 0x00040000, 0x00080000) + iadd r0.y, r0.y, r4.z + iadd r0.y, r4.w, r0.y + ishr r0.w, r6.x, l(1) + ishr r4.zw, r6.xxxy, l(2) + ishr r2.z, r6.x, l(3) + ishl r9.x, r0.w, l(20) + ishl r9.y, r4.z, l(21) + ishl r9.z, r2.z, l(22) + ishl r9.w, r4.w, l(6) + and r9.xyzw, r9.xyzw, l(0x00100000, 0x00200000, 0x00400000, 64) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r2.w, r0.y + ishr r0.w, r4.y, l(1) + ishr r2.z, r4.y, l(2) + ishr r2.w, r4.y, l(3) + ishr r4.z, r4.y, l(4) + ishl r10.x, r0.w, l(24) + ishl r10.y, r2.z, l(25) + ishl r10.z, r2.w, l(26) + ishl r10.w, r4.z, l(27) + and r10.xyzw, r10.xyzw, l(0x01000000, 0x02000000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r10.x + iadd r0.y, r10.y, r0.y + iadd r0.y, r10.z, r0.y + iadd r0.y, r10.w, r0.y + ishr r0.w, r4.y, l(5) + ishl r0.w, r0.w, l(28) + and r0.w, r0.w, l(0x10000000) + iadd r0.y, r0.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r3.z, r0.z, r0.y + ishr r0.yz, r5.zzxz, l(3) + ishr r0.w, r5.x, l(1) + ishr r2.z, r5.x, l(2) + and r0.y, r0.y, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + ishl r7.x, r0.w, l(2) + ishl r7.y, r2.z, l(3) + ishl r7.z, r0.z, l(4) + and r7.xyz, r7.xyzx, l(4, 8, 16, 0) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + ishr r0.z, r5.x, l(4) + ishr r0.w, r5.w, l(1) + ishr r2.z, r5.w, l(2) + ishr r2.w, r5.w, l(3) + ishl r8.x, r0.z, l(5) + ishl r8.y, r0.w, l(8) + ishl r8.z, r2.z, l(9) + ishl r8.w, r2.w, l(10) + and r8.xyzw, r8.xyzw, l(32, 256, 512, 1024) + iadd r0.y, r0.y, r8.x + iadd r0.y, r9.w, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r5.w, l(4) + ishl r0.z, r0.z, l(11) + and r0.z, r0.z, l(2048) + iadd r0.y, r0.z, r0.y + ishr r0.z, r6.y, l(3) + ishl r0.z, r0.z, l(12) + and r0.z, r0.z, l(4096) + iadd r0.y, r0.z, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r2.z, r2.y, l(3) + ushr r2.w, r2.y, l(4) + ishl r7.x, r0.z, l(14) + ishl r7.y, r0.w, l(15) + ishl r7.z, r2.z, l(16) + ishl r7.w, r2.w, l(17) + and r7.xyzw, r7.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r3.w, r7.w, r0.y + else + ieq r0.y, r2.x, l(10) + if_nz r0.y + ishl r7.x, r1.x, l(5) + ishl r7.y, r1.y, l(15) + ishl r7.z, r1.z, l(25) + ishl r7.w, r1.w, l(3) + and r7.xyzw, r7.xyzw, l(32, 0x00008000, 0x02000000, 8) + iadd r0.y, r7.x, l(30) + ishr r0.z, r1.x, l(1) + ishr r0.w, r1.x, l(2) + ishr r2.x, r1.x, l(3) + ishr r2.z, r1.x, l(4) + ishl r8.x, r0.z, l(6) + ishl r8.y, r0.w, l(7) + ishl r8.z, r2.x, l(8) + ishl r8.w, r2.z, l(9) + and r8.xyzw, r8.xyzw, l(64, 128, 256, 512) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.x, l(5) + ishr r0.w, r1.y, l(1) + ishr r1.x, r1.y, l(2) + ishr r2.x, r1.y, l(3) + ishl r8.x, r0.z, l(10) + ishl r8.y, r0.w, l(16) + ishl r8.z, r1.x, l(17) + ishl r8.w, r2.x, l(18) + and r8.xyzw, r8.xyzw, l(1024, 0x00010000, 0x00020000, 0x00040000) + iadd r0.y, r0.y, r8.x + ishr r0.z, r6.x, l(4) + ishr r0.w, r6.y, l(1) + ishr r1.x, r6.y, l(2) + ishr r2.x, r6.x, l(5) + ishl r9.x, r0.z, l(11) + ishl r9.y, r0.w, l(13) + ishl r9.z, r1.x, l(23) + ishl r0.z, r2.x, l(31) + and r2.xzw, r9.xxyz, l(2048, 0, 8192, 0x00800000) + iadd r0.y, r0.y, r2.x + ishl r9.x, r6.y, l(12) + ishl r9.y, r6.x, l(19) + and r4.zw, r9.xxxy, l(0, 0, 4096, 0x00080000) + iadd r0.y, r0.y, r4.z + iadd r0.y, r2.z, r0.y + ishr r2.xz, r5.zzyz, l(4) + ishr r6.zw, r5.yyyz, l(5) + ishl r9.x, r2.x, l(14) + ishl r9.y, r6.z, l(21) + ishl r9.z, r6.w, l(22) + ishl r9.w, r2.z, l(24) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00200000, 0x00400000, 0x01000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.w, r1.y, l(4) + ishr r1.x, r1.y, l(5) + ishr r1.y, r1.z, l(1) + ishr r2.x, r1.z, l(2) + ishl r8.x, r0.w, l(19) + ishl r8.y, r1.x, l(20) + ishl r8.z, r1.y, l(26) + ishl r8.w, r2.x, l(27) + and r8.xyzw, r8.xyzw, l(0x00080000, 0x00100000, 0x04000000, 0x08000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r2.w, r0.y + iadd r0.y, r9.w, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r8.z, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.w, r1.z, l(3) + ishr r1.x, r1.z, l(4) + ishr r1.y, r1.z, l(5) + ishr r1.z, r1.w, l(1) + ishl r8.x, r0.w, l(28) + ishl r8.y, r1.x, l(29) + ishl r8.z, r1.y, l(30) + ishl r8.w, r1.z, l(4) + and r8.xyzw, r8.xyzw, l(0x10000000, 0x20000000, 0x40000000, 16) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + iadd r3.x, r0.z, r0.y + ishr r0.y, r6.y, l(3) + ishr r0.z, r6.y, l(5) + ishr r0.w, r6.y, l(4) + ishr r1.x, r6.x, l(1) + and r0.y, r0.y, l(1) + ishl r7.x, r0.z, l(1) + ishl r7.y, r0.w, l(2) + ishl r7.z, r1.x, l(20) + and r1.xyz, r7.xyzx, l(2, 4, 0x00100000, 0) + iadd r0.y, r0.y, r1.x + iadd r0.y, r1.y, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.z, r1.w, l(2) + ishr r0.w, r1.w, l(3) + ishr r1.x, r1.w, l(4) + ishr r1.y, r1.w, l(5) + ishl r7.x, r0.z, l(5) + ishl r7.y, r0.w, l(6) + ishl r7.z, r1.x, l(7) + ishl r7.w, r1.y, l(8) + and r7.xyzw, r7.xyzw, l(32, 64, 128, 256) + iadd r0.y, r0.y, r7.x + iadd r0.y, r7.y, r0.y + iadd r0.y, r7.z, r0.y + iadd r0.y, r7.w, r0.y + ishl r7.x, r5.y, l(9) + ishl r7.y, r5.z, l(29) + ishl r7.z, r5.x, l(1) + ishl r7.w, r5.w, l(7) + and r7.xyzw, r7.xyzw, l(512, 0x20000000, 2, 128) + iadd r0.y, r0.y, r7.x + ishr r0.zw, r5.yyyz, l(1) + ishr r1.x, r5.y, l(2) + ishr r1.y, r5.y, l(3) + ishl r8.x, r0.z, l(10) + ishl r8.y, r1.x, l(11) + ishl r8.z, r1.y, l(12) + ishl r8.w, r0.w, l(30) + and r8.xyzw, r8.xyzw, l(1024, 2048, 4096, 0x40000000) + iadd r0.y, r0.y, r8.x + iadd r0.y, r8.y, r0.y + iadd r0.y, r8.z, r0.y + ishl r1.x, r4.x, l(13) + ishl r1.y, r4.y, l(23) + and r0.zw, r1.xxxy, l(0, 0, 8192, 0x00800000) + iadd r0.y, r0.z, r0.y + ishr r0.z, r4.x, l(1) + ishr r1.x, r4.x, l(2) + ishr r1.y, r4.x, l(3) + ishr r1.w, r4.x, l(4) + ishl r9.x, r0.z, l(14) + ishl r9.y, r1.x, l(15) + ishl r9.z, r1.y, l(16) + ishl r9.w, r1.w, l(17) + and r9.xyzw, r9.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r4.x, l(5) + ishr r1.x, r4.y, l(1) + ishr r1.y, r4.y, l(2) + ishr r1.w, r4.y, l(3) + ishl r9.x, r0.z, l(18) + ishl r9.y, r1.x, l(24) + ishl r9.z, r1.y, l(25) + ishl r9.w, r1.w, l(26) + and r9.xyzw, r9.xyzw, l(0x00040000, 0x01000000, 0x02000000, 0x04000000) + iadd r0.y, r0.y, r9.x + iadd r0.y, r4.w, r0.y + iadd r0.y, r1.z, r0.y + ishr r0.z, r6.x, l(2) + ishr r1.x, r6.x, l(3) + ishl r6.x, r0.z, l(21) + ishl r6.y, r1.x, l(22) + and r1.xy, r6.xyxx, l(0x00200000, 0x00400000, 0, 0) + iadd r0.y, r0.y, r1.x + iadd r0.y, r1.y, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r9.y, r0.y + iadd r0.y, r9.z, r0.y + iadd r0.y, r9.w, r0.y + ishr r0.z, r4.y, l(4) + ishr r0.w, r4.y, l(5) + ishl r1.x, r0.z, l(27) + ishl r1.y, r0.w, l(28) + and r0.zw, r1.xxxy, l(0, 0, 0x08000000, 0x10000000) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + iadd r0.y, r7.y, r0.y + iadd r0.y, r8.w, r0.y + ishr r0.zw, r5.zzzx, l(2) + ishr r1.x, r5.z, l(3) + ishr r1.y, r5.x, l(1) + ishl r4.x, r0.z, l(31) + ishl r4.y, r1.y, l(2) + ishl r4.z, r0.w, l(3) + iadd r3.z, r0.y, r4.x + and r0.y, r1.x, l(1) + iadd r0.y, r0.y, r3.w + iadd r0.y, r7.z, r0.y + and r0.zw, r4.yyyz, l(0, 0, 4, 8) + iadd r0.y, r0.z, r0.y + iadd r0.y, r0.w, r0.y + ishr r0.z, r5.x, l(3) + ishr r0.w, r5.x, l(4) + ishr r1.x, r5.x, l(5) + ishr r1.y, r5.w, l(1) + ishl r4.x, r0.z, l(4) + ishl r4.y, r0.w, l(5) + ishl r4.z, r1.x, l(6) + ishl r4.w, r1.y, l(8) + and r1.xyzw, r4.xyzw, l(16, 32, 64, 256) + iadd r0.y, r0.y, r1.x + iadd r0.y, r1.y, r0.y + iadd r0.y, r1.z, r0.y + iadd r0.y, r7.w, r0.y + iadd r0.y, r1.w, r0.y + ishr r0.z, r5.w, l(2) + ishr r0.w, r5.w, l(3) + ishr r1.x, r5.w, l(4) + ishr r1.y, r5.w, l(5) + ishl r4.x, r0.z, l(9) + ishl r4.y, r0.w, l(10) + ishl r4.z, r1.x, l(11) + ishl r4.w, r1.y, l(12) + and r1.xyzw, r4.xyzw, l(512, 1024, 2048, 4096) + iadd r0.y, r0.y, r1.x + iadd r0.y, r1.y, r0.y + iadd r0.y, r1.z, r0.y + iadd r0.y, r1.w, r0.y + ishl r0.z, r2.y, l(13) + and r0.z, r0.z, l(8192) + iadd r0.y, r0.z, r0.y + ushr r0.z, r2.y, l(1) + ushr r0.w, r2.y, l(2) + ushr r1.x, r2.y, l(3) + ushr r1.y, r2.y, l(4) + ishl r2.x, r0.z, l(14) + ishl r2.y, r0.w, l(15) + ishl r2.z, r1.x, l(16) + ishl r2.w, r1.y, l(17) + and r1.xyzw, r2.xyzw, l(0x00004000, 0x00008000, 0x00010000, 0x00020000) + iadd r0.y, r0.y, r1.x + iadd r0.y, r1.y, r0.y + iadd r0.y, r1.z, r0.y + iadd r3.w, r1.w, r0.y + else + mov r3.xz, l(0,0,0,0) + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + store_structured u0.xyzw, r0.x, l(0), r3.xzwy +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC6HEncode_EncodeBlockCS[] = +{ + 68, 88, 66, 67, 106, 242, + 47, 44, 29, 251, 192, 175, + 230, 64, 141, 23, 223, 196, + 86, 63, 1, 0, 0, 0, + 28, 173, 1, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 200, 172, 1, 0, + 64, 0, 5, 0, 50, 107, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 58, 1, + 0, 0, 204, 204, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 136, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 238, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 236, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 128, 200, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 236, 254, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 200, 254, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 128, 236, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 200, + 0, 0, 15, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 236, 255, 0, 0, + 15, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 128, 254, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 232, + 0, 0, 15, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 232, 255, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 0, 255, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 240, 255, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 0, 240, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 16, 247, 0, 0, 15, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 142, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 113, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 206, 8, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 140, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 2, 0, + 0, 0, 16, 115, 0, 0, + 8, 0, 0, 0, 5, 0, + 0, 0, 2, 0, 0, 0, + 0, 49, 0, 0, 8, 0, + 0, 0, 5, 0, 0, 0, + 2, 0, 0, 0, 206, 140, + 0, 0, 15, 0, 0, 0, + 5, 0, 0, 0, 3, 0, + 0, 0, 140, 8, 0, 0, + 2, 0, 0, 0, 6, 0, + 0, 0, 3, 0, 0, 0, + 16, 49, 0, 0, 8, 0, + 0, 0, 6, 0, 0, 0, + 3, 0, 0, 0, 102, 102, + 0, 0, 2, 0, 0, 0, + 6, 0, 0, 0, 3, 0, + 0, 0, 108, 54, 0, 0, + 2, 0, 0, 0, 6, 0, + 0, 0, 3, 0, 0, 0, + 232, 23, 0, 0, 8, 0, + 0, 0, 6, 0, 0, 0, + 3, 0, 0, 0, 240, 15, + 0, 0, 8, 0, 0, 0, + 7, 0, 0, 0, 3, 0, + 0, 0, 142, 113, 0, 0, + 2, 0, 0, 0, 7, 0, + 0, 0, 3, 0, 0, 0, + 156, 57, 0, 0, 2, 0, + 0, 0, 7, 0, 0, 0, + 3, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 7, 0, 0, 0, 3, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 9, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 9, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 9, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 9, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 5, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 10, 0, 0, 0, + 5, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 10, 0, 0, 0, 5, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 10, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 7, 0, 0, 0, + 10, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 5, 0, 0, 0, 7, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 0, 0, 11, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 11, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 11, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 5, 0, + 0, 0, 9, 0, 0, 0, + 5, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 6, 0, + 0, 0, 5, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 5, 0, 0, 0, + 6, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 5, 0, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 11, 0, 0, 0, + 9, 0, 0, 0, 9, 0, + 0, 0, 9, 0, 0, 0, + 12, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 162, 0, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 0, 158, 0, 0, 4, + 0, 224, 17, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 95, 0, 0, 2, 0, 64, + 2, 0, 95, 0, 0, 2, + 18, 16, 2, 0, 104, 0, + 0, 2, 18, 0, 0, 0, + 160, 0, 0, 5, 0, 240, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 0, 64, 0, + 0, 0, 155, 0, 0, 4, + 64, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 6, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 16, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 79, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 78, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 0, 208, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 11, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 7, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 126, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 10, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 208, 179, + 89, 62, 89, 23, 55, 63, + 152, 221, 147, 61, 0, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 4, 0, 0, 0, + 6, 5, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 127, 255, 255, + 127, 0, 255, 255, 255, 127, + 255, 255, 127, 0, 79, 0, + 0, 10, 50, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 239, 255, 71, + 255, 239, 255, 71, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 0, 16, 0, 4, 0, + 0, 0, 79, 0, 0, 10, + 50, 0, 16, 0, 5, 0, + 0, 0, 134, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 56, + 0, 0, 128, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 194, 0, + 16, 0, 5, 0, 0, 0, + 6, 8, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 30, 0, + 0, 11, 194, 0, 16, 0, + 5, 0, 0, 0, 166, 14, + 16, 128, 65, 0, 0, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 113, 0, + 0, 0, 113, 0, 0, 0, + 30, 0, 0, 10, 162, 0, + 16, 0, 4, 0, 0, 0, + 86, 13, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 128, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 4, 0, 0, 0, + 134, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 200, 0, 0, + 0, 200, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 50, 0, 16, 0, + 4, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 30, 0, + 0, 10, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 15, 0, 0, 255, 15, + 0, 0, 85, 0, 0, 7, + 50, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 10, 50, 0, + 16, 0, 4, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 50, 0, 16, 0, + 4, 0, 0, 0, 70, 0, + 16, 0, 4, 0, 0, 0, + 230, 10, 16, 0, 4, 0, + 0, 0, 85, 0, 0, 7, + 50, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 10, 50, 0, + 16, 0, 4, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 50, 0, 16, 0, + 2, 0, 0, 0, 70, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 30, 0, + 0, 7, 50, 0, 16, 0, + 4, 0, 0, 0, 70, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 50, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 127, + 255, 255, 127, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 239, + 255, 71, 10, 0, 16, 0, + 2, 0, 0, 0, 79, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 56, 85, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 113, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 0, + 85, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 200, 55, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 255, 15, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 255, 127, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 255, 127, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 32, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 95, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 78, 0, 0, 11, 114, 0, + 16, 0, 2, 0, 0, 0, + 0, 208, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 31, 0, 0, 0, 0, 0, + 0, 0, 79, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 123, 0, 0, 255, 123, + 0, 0, 255, 123, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 78, 0, 0, 11, + 114, 0, 16, 0, 6, 0, + 0, 0, 0, 208, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 224, 255, + 15, 0, 224, 255, 15, 0, + 224, 255, 15, 0, 0, 0, + 0, 0, 78, 0, 0, 11, + 114, 0, 16, 0, 4, 0, + 0, 0, 0, 208, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 1, 128, 255, 255, 1, 128, + 255, 255, 1, 128, 255, 255, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 167, 0, + 0, 9, 50, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 70, 112, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 130, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 79, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 242, 0, + 16, 0, 5, 0, 0, 0, + 150, 15, 16, 0, 3, 0, + 0, 0, 18, 0, 0, 1, + 85, 0, 0, 8, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 144, 144, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 4, 0, 0, 0, + 86, 5, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 127, 255, 255, + 255, 127, 255, 255, 255, 127, + 0, 0, 0, 128, 70, 2, + 16, 0, 3, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 5, 0, 0, 0, + 86, 5, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 128, 0, 0, + 0, 128, 255, 255, 127, 127, + 255, 255, 127, 255, 150, 15, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 18, 0, + 0, 1, 80, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 85, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 144, 144, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 32, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 12, 242, 0, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 127, 255, 255, + 255, 127, 255, 255, 255, 127, + 0, 0, 0, 128, 55, 0, + 0, 12, 242, 0, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 150, 15, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 128, 0, 0, + 0, 128, 255, 255, 127, 127, + 255, 255, 127, 255, 18, 0, + 0, 1, 54, 0, 0, 8, + 242, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 127, 255, 255, + 255, 127, 255, 255, 255, 127, + 0, 0, 0, 128, 54, 0, + 0, 8, 242, 0, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 128, + 0, 0, 0, 128, 255, 255, + 127, 127, 255, 255, 127, 255, + 21, 0, 0, 1, 21, 0, + 0, 1, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 190, 24, + 0, 1, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 79, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 3, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 76, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 8, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 80, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 3, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 76, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 8, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 80, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 3, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 76, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 8, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 80, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 58, 0, 16, 0, + 3, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 167, 0, + 0, 8, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 32, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 58, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 144, 144, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 30, 0, 0, 8, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 49, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 29, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 28, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 55, 0, 0, 9, 194, 0, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 86, 9, 16, 0, + 3, 0, 0, 0, 86, 9, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 168, 0, 0, 8, + 50, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 230, 10, 16, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 6, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 144, + 144, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 85, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 4, 0, 0, 0, 43, 0, + 0, 5, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 167, 0, 0, 8, 114, 0, + 16, 0, 5, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 43, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 16, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 18, 0, + 0, 1, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 5, 0, 0, 0, 43, 0, + 0, 5, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 167, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 43, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 16, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 16, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 29, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 29, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 14, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 28, 0, 0, 5, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 10, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 144, + 144, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 79, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 224, 255, + 255, 255, 41, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 8, 98, 0, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 9, + 194, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 4, 0, 0, 0, + 166, 14, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 18, 0, + 0, 1, 29, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 29, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 49, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 14, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 28, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 55, 0, + 0, 10, 18, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 58, 144, 144, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 0, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 79, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 35, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 39, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 26, 144, + 144, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 32, 0, + 0, 8, 34, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 26, 144, 144, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 79, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 1, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 55, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 79, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 35, 0, 0, 12, + 194, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 166, 14, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 166, 14, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 255, + 255, 255, 240, 255, 255, 255, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 168, 0, 0, 8, + 50, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 8, + 50, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 50, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 50, 0, 16, 0, 1, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 79, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 50, 0, 16, 0, 4, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 146, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 5, 0, + 0, 0, 168, 0, 0, 8, + 50, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 198, 0, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 50, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 146, 0, 16, 0, 1, 0, + 0, 0, 6, 4, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 5, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 198, 0, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 50, 0, 16, 0, + 4, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 190, 24, 0, 1, + 30, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 32, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 32, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 95, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 33, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 0, 0, 0, 0, + 41, 0, 0, 9, 18, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 41, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 10, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 10, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 18, 0, 0, 1, 33, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 10, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 41, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 17, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 21, 0, 0, 1, 30, 0, + 0, 8, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 55, 0, 0, 11, 114, 0, + 16, 0, 4, 0, 0, 0, + 6, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 150, 5, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 80, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 32, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 95, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 33, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 60, 0, + 0, 7, 178, 0, 16, 0, + 1, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 70, 8, 16, 0, 8, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 9, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 10, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 9, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 10, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 166, 10, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 166, 10, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 55, 0, + 0, 9, 178, 0, 16, 0, + 1, 0, 0, 0, 70, 12, + 16, 0, 1, 0, 0, 0, + 70, 8, 16, 0, 6, 0, + 0, 0, 70, 8, 16, 0, + 9, 0, 0, 0, 18, 0, + 0, 1, 33, 0, 0, 9, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 8, 0, 0, 0, + 166, 10, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 33, 0, 0, 10, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 9, 66, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 10, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 7, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 246, 15, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 246, 15, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 2, 64, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 17, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 178, 0, 16, 0, + 1, 0, 0, 0, 70, 8, + 16, 0, 9, 0, 0, 0, + 70, 8, 16, 0, 6, 0, + 0, 0, 70, 8, 16, 0, + 11, 0, 0, 0, 21, 0, + 0, 1, 30, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 8, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 4, 0, 0, 0, 70, 3, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 55, 0, + 0, 11, 242, 0, 16, 0, + 5, 0, 0, 0, 6, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 55, 0, 0, 11, 50, 0, + 16, 0, 1, 0, 0, 0, + 6, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 150, 5, + 16, 0, 4, 0, 0, 0, + 214, 5, 16, 0, 1, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 6, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 150, 240, + 17, 0, 0, 0, 0, 0, + 31, 0, 0, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 9, 18, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 9, 34, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 26, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 9, 66, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 9, 130, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 58, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 6, 0, 0, 0, 38, 9, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 12, + 114, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 0, 0, 0, 0, 150, 151, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 33, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 38, 9, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 0, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 38, 9, 16, 0, + 1, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 9, 0, 0, 0, 38, 9, + 16, 0, 1, 0, 0, 0, + 34, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 1, 0, 0, 7, + 226, 0, 16, 0, 5, 0, + 0, 0, 166, 4, 16, 0, + 1, 0, 0, 0, 86, 14, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 226, 0, + 16, 0, 5, 0, 0, 0, + 6, 9, 16, 0, 9, 0, + 0, 0, 6, 9, 16, 0, + 8, 0, 0, 0, 86, 14, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 226, 0, + 16, 0, 5, 0, 0, 0, + 6, 9, 16, 0, 6, 0, + 0, 0, 6, 9, 16, 0, + 7, 0, 0, 0, 86, 14, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 6, 0, + 16, 0, 5, 0, 0, 0, + 1, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 5, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 55, 0, 0, 11, + 242, 0, 16, 0, 4, 0, + 0, 0, 6, 144, 208, 0, + 32, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 11, 50, 0, 16, 0, + 1, 0, 0, 0, 6, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 230, 10, 16, 0, + 5, 0, 0, 0, 230, 10, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 5, 10, 144, 208, 0, + 32, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 9, 34, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 26, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 9, 66, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 9, 130, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 58, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 1, 0, + 0, 7, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 6, 0, 16, 0, 5, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 38, 9, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 12, 114, 0, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, + 0, 0, 150, 151, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 33, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 38, 9, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 38, 9, 16, 0, 1, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 9, 0, + 0, 0, 38, 9, 16, 0, + 1, 0, 0, 0, 34, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 5, 0, + 0, 0, 38, 9, 16, 0, + 1, 0, 0, 0, 150, 7, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 150, 4, 16, 0, 6, 0, + 0, 0, 150, 4, 16, 0, + 7, 0, 0, 0, 150, 4, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 18, 0, 0, 1, + 41, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 144, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 5, 130, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 242, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 7, 50, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 18, 0, + 0, 1, 80, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 5, 10, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 12, 114, 0, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, + 0, 0, 150, 151, 208, 0, + 64, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 33, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 34, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 41, 0, 0, 9, + 18, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 26, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 9, + 34, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 9, + 66, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 58, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 38, 9, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 38, 9, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 38, 9, + 16, 0, 1, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 8, 0, 0, 0, + 38, 9, 16, 0, 1, 0, + 0, 0, 34, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 1, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 38, 9, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 150, 4, + 16, 0, 5, 0, 0, 0, + 150, 4, 16, 0, 6, 0, + 0, 0, 150, 4, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 18, 0, 0, 1, 41, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 144, 208, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 54, 0, 0, 5, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 242, 0, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 1, 0, 0, 7, + 50, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 21, 0, 0, 1, 18, 0, + 0, 1, 54, 0, 0, 5, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 50, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 70, 0, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 0, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 254, 255, + 255, 255, 32, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 2, 8, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 0, 64, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 2, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 0, 4, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 27, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 0, 64, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 2, 8, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 4, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 4, 0, 0, 0, 8, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 0, 64, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 128, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 128, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 0, 0, + 32, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 4, 0, 0, 0, + 86, 9, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 64, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 0, 64, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 2, + 8, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 64, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 4, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 27, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 0, 4, + 0, 0, 0, 8, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 0, 64, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 2, 0, 0, 0, 4, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 0, 16, + 0, 0, 0, 0, 32, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 8, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 0, 1, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 4, 0, + 0, 0, 86, 9, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 64, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, + 0, 0, 0, 64, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 2, + 8, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 64, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 4, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 27, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 0, 4, + 0, 0, 0, 8, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 0, 64, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 2, 0, 0, 0, 4, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 0, 16, + 0, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 8, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 64, 0, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 0, 32, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 4, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 8, 82, 0, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 18, 0, + 0, 1, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 252, 255, 32, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 98, 0, 16, 0, 0, 0, + 0, 0, 86, 6, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 2, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 4, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 4, 0, 0, 0, 8, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 0, 64, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 1, + 0, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 32, + 2, 0, 0, 0, 128, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 0, 0, + 0, 0, 86, 9, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 64, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 6, 0, + 0, 0, 6, 4, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 0, 8, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 16, 64, 0, 0, 0, + 0, 16, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 98, 0, 16, 0, 0, 0, + 0, 0, 86, 6, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 166, 6, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 0, 64, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 1, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 2, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 10, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 10, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 8, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 32, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 134, 3, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 64, + 16, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 64, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 2, 0, 0, 0, 0, + 0, 32, 2, 0, 0, 0, + 128, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 2, 0, + 0, 0, 86, 9, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 0, 0, 64, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 10, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 0, 4, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 0, 0, 0, 16, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 2, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 86, 9, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 0, 1, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 2, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 0, 64, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 2, 0, 0, + 0, 0, 0, 32, 2, 0, + 0, 0, 128, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 86, 9, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 64, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 128, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 1, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 86, 9, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 27, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 8, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 0, 16, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, + 0, 0, 0, 4, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 2, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 86, 9, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 64, 0, + 0, 0, 0, 16, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 2, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 0, 64, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 4, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 1, + 0, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 32, + 2, 0, 0, 0, 128, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 86, 9, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 10, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 0, + 0, 64, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 32, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 16, 64, 0, + 0, 0, 0, 16, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 2, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 86, 9, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 12, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 16, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 8, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 32, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 128, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 2, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 4, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 4, 0, 0, 0, 8, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 0, 64, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 1, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 2, 0, 0, + 0, 0, 0, 32, 2, 0, + 0, 0, 128, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 128, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 32, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 16, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 2, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 4, 0, + 0, 0, 6, 8, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 64, 4, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 12, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 8, 0, + 0, 0, 16, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 4, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 32, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 128, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 2, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 6, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 1, + 0, 4, 0, 0, 0, 8, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 32, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 8, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 64, 2, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 86, 1, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 0, 1, 0, 0, + 0, 0, 16, 0, 0, 0, + 32, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 32, + 2, 0, 0, 0, 128, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 0, 0, + 0, 0, 86, 9, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 64, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 6, 0, + 0, 0, 6, 4, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 6, 0, 0, 0, 6, 4, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 64, 0, + 0, 0, 0, 16, 64, 0, + 0, 0, 0, 16, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 2, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 0, 1, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 6, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 1, 0, 4, + 0, 0, 0, 8, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 27, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 0, 4, + 0, 0, 0, 8, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 32, + 0, 0, 0, 64, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 2, 0, 0, + 0, 0, 0, 32, 2, 0, + 0, 0, 128, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 86, 9, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, + 0, 0, 0, 64, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 6, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 6, 0, 0, 0, + 6, 4, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 0, 16, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 0, 8, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 32, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 2, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 4, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 0, 1, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 8, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 2, 0, + 0, 0, 166, 6, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 4, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 0, 64, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 6, 0, 0, 0, 86, 1, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 16, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 128, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 2, 0, 0, 0, 0, + 0, 32, 2, 0, 0, 0, + 128, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 86, 9, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 8, + 0, 0, 0, 16, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 0, 4, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 194, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 10, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 0, 16, 64, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 98, 0, 16, 0, + 0, 0, 0, 0, 166, 8, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 0, 4, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 8, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 16, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 32, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 128, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 2, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 0, 2, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 0, + 1, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 2, 0, 0, 0, 86, 1, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 32, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 0, 1, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 6, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 10, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 0, + 128, 0, 0, 0, 0, 1, + 0, 4, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 10, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 32, 0, 0, 0, 64, 0, + 0, 0, 0, 4, 0, 0, + 0, 8, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 16, + 0, 0, 0, 32, 0, 0, + 0, 64, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 128, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 32, + 2, 0, 0, 0, 128, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 86, 9, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 0, 0, + 0, 64, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, + 128, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 128, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 16, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 64, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 0, 4, 0, 0, 0, 8, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 16, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 98, 0, 16, 0, 0, 0, + 0, 0, 166, 8, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 0, 4, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 8, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 16, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 2, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 64, 0, + 0, 0, 128, 0, 0, 0, + 0, 1, 0, 0, 0, 2, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 4, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 4, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 1, 0, 0, 10, 210, 0, + 16, 0, 2, 0, 0, 0, + 6, 9, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 8, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, + 0, 0, 128, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 4, 0, 0, 0, 6, 4, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 0, + 8, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 82, 0, 16, 0, + 2, 0, 0, 0, 166, 9, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 194, 0, 16, 0, 6, 0, + 0, 0, 86, 9, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 32, 0, + 0, 0, 64, 0, 0, 0, + 0, 1, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 27, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 0, 4, + 0, 0, 0, 8, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 8, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 16, 0, 0, + 0, 32, 0, 0, 0, 64, + 16, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 128, 0, + 0, 0, 0, 1, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 2, 0, 0, + 0, 0, 0, 32, 2, 0, + 0, 0, 128, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 86, 9, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 64, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 128, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 42, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 128, + 0, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 42, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, + 0, 4, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 42, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 16, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 2, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 86, 9, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 64, 0, 0, 0, 0, 1, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 42, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 42, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 42, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 2, 0, 0, 0, 4, + 0, 0, 0, 8, 0, 0, + 0, 16, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 64, + 0, 0, 0, 128, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 8, 82, 0, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 168, 0, 0, 9, + 242, 224, 17, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 134, 7, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 62, 0, 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_EncodeBlockCS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_EncodeBlockCS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..f5a86ff7c30834d53427ccdc6bdfecaa67f4e78a Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_EncodeBlockCS.pdb differ diff --git a/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeG10CS.inc b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeG10CS.inc new file mode 100644 index 0000000000000000000000000000000000000000..18a4e87f8192cbb31573d37bf5af2e10f07a38bb --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeG10CS.inc @@ -0,0 +1,3366 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { 10, 5, 5, 5}, + { 7, 6, 6, 6}, + { 11, 5, 4, 4}, + { 11, 4, 5, 4}, + { 11, 4, 4, 5}, + { 9, 5, 5, 5}, + { 8, 6, 5, 5}, + { 8, 5, 6, 5}, + { 8, 5, 5, 6}, + { 6, 6, 6, 6}, + { 10, 10, 10, 10}, + { 11, 9, 9, 9}, + { 12, 8, 8, 8}, + { 16, 4, 4, 4}, + { -1, 0, 0, 0}, + { -1, 0, 4, 0}, + { -1, 0, 9, 0}, + { -1, 1, 13, 0}, + { -1, 1, 17, 0}, + { -1, 1, 21, 0}, + { -1, 1, 26, 0}, + { -1, 2, 30, 0}, + { -1, 2, 34, 0}, + { 0, 2, 38, 0}, + { 0, 2, 43, 0}, + { -1, 2, 47, 0}, + { -1, 3, 51, 0}, + { -1, 3, 55, 0}, + { 0, 3, 60, 0}, + { 0, 3, 64, 0}, + { 0, 4, 0, 0}, + { 0, 4, 0, 0}, + { 0, 4, 0, 0}, + { 0, 4, 0, 0}, + { 0, 5, 0, 0}, + { 0, 5, 0, 0}, + { 0, 5, 0, 0}, + { 0, 5, 0, 0}, + { 0, 6, 0, 0}, + { 0, 6, 0, 0}, + { 0, 6, 0, 0}, + { 0, 6, 0, 0}, + { 0, 6, 0, 0}, + { 0, 7, 0, 0}, + { 0, 7, 0, 0}, + { 0, 7, 0, 0}, + { 0, 7, 0, 0}, + { 0, 8, 0, 0}, + { 0, 8, 0, 0}, + { 0, 8, 0, 0}, + { 0, 8, 0, 0}, + { 0, 9, 0, 0}, + { 0, 9, 0, 0}, + { 0, 9, 0, 0}, + { 0, 9, 0, 0}, + { 0, 10, 0, 0}, + { 0, 10, 0, 0}, + { 0, 10, 0, 0}, + { 0, 10, 0, 0}, + { 0, 10, 0, 0}, + { 0, 11, 0, 0}, + { 0, 11, 0, 0}, + { 0, 11, 0, 0}, + { 0, 11, 0, 0}, + { 0, 12, 0, 0}, + { 0, 12, 0, 0}, + { 0, 12, 0, 0}, + { 0, 12, 0, 0}, + { 0, 13, 0, 0}, + { 0, 13, 0, 0}, + { 0, 13, 0, 0}, + { 0, 13, 0, 0}, + { 0, 14, 0, 0}, + { 0, 14, 0, 0}, + { 0, 14, 0, 0}, + { 0, 14, 0, 0}, + { 0, 15, 0, 0}, + { 0, 15, 0, 0} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 19 +dcl_tgsm_structured g0, 84, 64 +dcl_thread_group 64, 1, 1 +ushr r0.x, vThreadIDInGroupFlattened.x, l(4) +ishl r0.y, vThreadGroupID.x, l(2) +iadd r0.y, r0.y, cb0[1].x +iadd r0.x, r0.x, r0.y +and r0.y, vThreadIDInGroupFlattened.x, l(48) +iadd r0.z, -r0.y, vThreadIDInGroupFlattened.x +ult r1.xyzw, r0.zzzz, l(16, 8, 4, 2) +if_nz r1.x + udiv r0.w, null, r0.x, cb0[0].y + imad r1.x, -r0.w, cb0[0].y, r0.x + ishl r1.x, r1.x, l(2) + ishl r0.w, r0.w, l(2) + and r2.x, r0.z, l(3) + iadd r2.x, r1.x, r2.x + ushr r1.x, r0.z, l(2) + iadd r2.y, r0.w, r1.x + mov r2.zw, l(0,0,0,0) + ld r2.xyzw, r2.xyzw, t0.xyzw + ushr r3.xyz, r2.xyzx, l(16) + and r3.xyz, r3.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + and r4.xyzw, r2.xxyy, l(0x7fffffff, 0x007fffff, 0x7fffffff, 0x007fffff) + ult r2.xy, l(0x47ffefff, 0x47ffefff, 0, 0), r4.xzxx + ult r5.xy, r4.xzxx, l(0x38800000, 0x38800000, 0, 0) + ushr r5.zw, r4.xxxz, l(23) + iadd r5.zw, -r5.zzzw, l(0, 0, 113, 113) + iadd r4.yw, r4.yyyw, l(0, 0x00800000, 0, 0x00800000) + ushr r6.x, r4.y, r5.z + ushr r6.y, r4.w, r5.w + iadd r4.xy, r4.xzxx, l(0xc8000000, 0xc8000000, 0, 0) + movc r4.xy, r5.xyxx, r6.xyxx, r4.xyxx + iadd r4.zw, r4.xxxy, l(0, 0, 4095, 4095) + ushr r4.xy, r4.xyxx, l(13) + and r4.xy, r4.xyxx, l(1, 1, 0, 0) + iadd r4.xy, r4.xyxx, r4.zwzz + ushr r4.xy, r4.xyxx, l(13) + and r4.xy, r4.xyxx, l(0x00007fff, 0x00007fff, 0, 0) + movc r2.xy, r2.xyxx, l(0x00007fff,0x00007fff,0,0), r4.xyxx + iadd r4.xy, r3.xyxx, r2.xyxx + and r2.xy, r2.zzzz, l(0x7fffffff, 0x007fffff, 0, 0) + ult r0.w, l(0x47ffefff), r2.x + ult r1.x, r2.x, l(0x38800000) + ushr r2.z, r2.x, l(23) + iadd r2.z, -r2.z, l(113) + iadd r2.y, r2.y, l(0x00800000) + ushr r2.y, r2.y, r2.z + iadd r2.x, r2.x, l(0xc8000000) + movc r1.x, r1.x, r2.y, r2.x + iadd r2.x, r1.x, l(4095) + ushr r1.x, r1.x, l(13) + and r1.x, r1.x, l(1) + iadd r1.x, r1.x, r2.x + ushr r1.x, r1.x, l(13) + and r1.x, r1.x, l(0x00007fff) + movc r0.w, r0.w, l(0x00007fff), r1.x + iadd r4.z, r3.z, r0.w + and r2.xyzw, r4.xxyy, l(1023, 0x00007c00, 1023, 0x00007c00) + if_nz r2.y + ushr r0.w, r4.x, l(10) + and r0.w, r0.w, l(31) + else + if_nz r2.x + ishl r1.x, r2.x, l(1) + mov r2.y, r1.x + mov r0.w, l(0) + loop + and r3.x, r2.y, l(1024) + breakc_nz r3.x + iadd r0.w, r0.w, l(-1) + ishl r2.y, r2.y, l(1) + endloop + and r2.x, r2.y, l(1022) + else + mov r2.x, l(0) + mov r0.w, l(-112) + endif + endif + ishl r3.xyz, r4.xyzx, l(16) + and r3.xyz, r3.xyzx, l(0x80000000, 0x80000000, 0x80000000, 0) + ishl r0.w, r0.w, l(23) + iadd r0.w, r0.w, l(0x38000000) + or r0.w, r0.w, r3.x + ishl r1.x, r2.x, l(13) + iadd r5.x, r0.w, r1.x + if_nz r2.w + ushr r0.w, r4.y, l(10) + and r0.w, r0.w, l(31) + else + if_nz r2.z + ishl r1.x, r2.z, l(1) + mov r2.x, r1.x + mov r0.w, l(0) + loop + and r2.y, r2.x, l(1024) + breakc_nz r2.y + iadd r0.w, r0.w, l(-1) + ishl r2.x, r2.x, l(1) + endloop + and r2.z, r2.x, l(1022) + else + mov r2.z, l(0) + mov r0.w, l(-112) + endif + endif + ishl r0.w, r0.w, l(23) + iadd r0.w, r0.w, l(0x38000000) + or r0.w, r0.w, r3.y + ishl r1.x, r2.z, l(13) + iadd r5.y, r0.w, r1.x + and r2.xy, r4.zzzz, l(1023, 0x00007c00, 0, 0) + if_nz r2.y + ushr r0.w, r4.z, l(10) + and r0.w, r0.w, l(31) + else + if_nz r2.x + ishl r1.x, r2.x, l(1) + mov r2.y, r1.x + mov r0.w, l(0) + loop + and r2.z, r2.y, l(1024) + breakc_nz r2.z + iadd r0.w, r0.w, l(-1) + ishl r2.y, r2.y, l(1) + endloop + and r2.x, r2.y, l(1022) + else + mov r2.x, l(0) + mov r0.w, l(-112) + endif + endif + ishl r0.w, r0.w, l(23) + iadd r0.w, r0.w, l(0x38000000) + or r0.w, r0.w, r3.z + ishl r1.x, r2.x, l(13) + iadd r5.z, r0.w, r1.x + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(24), r5.xyzx + dp3 r2.w, r5.xyzx, l(0.212600, 0.715200, 0.072200, 0.000000) + ieq r0.w, cb0[0].z, l(95) + ishl r3.xyz, r4.xyzx, l(6) + udiv r3.xyz, null, r3.xyzx, l(31, 31, 31, 0) + ult r5.xyz, r4.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + ieq r6.xyz, r4.xyzx, l(0x00007bff, 0x00007bff, 0x00007bff, 0) + ishl r4.xyz, r4.xyzx, l(5) + udiv r7.xyz, null, r4.xyzx, l(31, 31, 31, 0) + movc r7.xyz, r6.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r7.xyzx + and r4.xyz, r4.xyzx, l(0x000fffe0, 0x000fffe0, 0x000fffe0, 0) + udiv r4.xyz, null, r4.xyzx, l(31, 31, 31, 0) + ineg r4.xyz, r4.xyzx + movc r4.xyz, r6.xyzx, l(0xffff8001,0xffff8001,0xffff8001,0), r4.xyzx + movc r4.xyz, r5.xyzx, r7.xyzx, r4.xyzx + movc r2.xyz, r0.wwww, r3.xyzx, r4.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(12), r2.xyzx + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r2.xyzx + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(68), r2.yzww +endif +sync_g_t +if_nz r1.y + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(8) + ld_structured r3.x, r0.w, l(76), g0.xxxx + lt r1.x, r3.x, r2.x + if_nz r1.x + ld_structured r2.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r2.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(76), r3.x + endif + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r3.x, r0.w, l(80), g0.xxxx + lt r1.x, r2.x, r3.x + if_nz r1.x + ld_structured r2.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r2.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(80), r3.x + endif +endif +sync_g_t +if_nz r1.z + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(4) + ld_structured r3.x, r0.w, l(76), g0.xxxx + lt r1.x, r3.x, r2.x + if_nz r1.x + ld_structured r2.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r2.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(76), r3.x + endif + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r3.x, r0.w, l(80), g0.xxxx + lt r1.x, r2.x, r3.x + if_nz r1.x + ld_structured r2.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r2.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(80), r3.x + endif +endif +sync_g_t +if_nz r1.w + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r0.w, vThreadIDInGroupFlattened.x, l(2) + ld_structured r3.x, r0.w, l(76), g0.xxxx + lt r1.x, r3.x, r2.x + if_nz r1.x + ld_structured r2.xyz, r0.w, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r2.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(76), r3.x + endif + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r3.x, r0.w, l(80), g0.xxxx + lt r1.x, r2.x, r3.x + if_nz r1.x + ld_structured r2.xyz, r0.w, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r2.xyzx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(80), r3.x + endif +endif +sync_g_t +ult r0.w, r0.z, l(1) +if_nz r0.w + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(76), g0.xxxx + iadd r1.x, vThreadIDInGroupFlattened.x, l(1) + ld_structured r3.x, r1.x, l(76), g0.xxxx + lt r1.y, r3.x, r2.x + if_nz r1.y + ld_structured r2.xyz, r1.x, l(52), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(52), r2.xyzx + endif + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(80), g0.xxxx + ld_structured r3.x, r1.x, l(80), g0.xxxx + lt r1.y, r2.x, r3.x + if_nz r1.y + ld_structured r2.xyz, r1.x, l(64), g0.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(64), r2.xyzx + endif +endif +sync_g_t +if_z r0.z + ld_structured r2.xyz, r0.y, l(52), g0.xyzx + ld_structured r3.xyz, r0.y, l(64), g0.xyzx + iadd r4.xyz, -r2.xyzx, r3.xyzx + itof r4.xyz, r4.xyzx + dp3 r1.x, r4.xyzx, r4.xyzx + ld_structured r5.xyz, r0.y, l(12), g0.xyzx + iadd r5.xyz, -r2.xyzx, r5.xyzx + itof r5.xyz, r5.xyzx + dp3 r1.y, r4.xyzx, r5.xyzx + lt r2.w, l(0.000000), r1.x + ge r4.x, r1.y, l(0.000000) + and r2.w, r2.w, r4.x + mul r1.y, r1.y, l(63.499989) + div r1.x, r1.y, r1.x + ftou r1.x, r1.x + ult r1.x, l(32), r1.x + and r1.x, r1.x, r2.w + if_nz r1.x + mov r3.w, r2.x + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r3.xyzw + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(68), r2.yzyy + endif +endif +sync_g_t +if_nz r1.z + ld_structured r2.xyz, r0.y, l(52), g0.xyzx + ld_structured r3.xyz, r0.y, l(64), g0.xyzx + ineg r1.xyz, r2.xyzx + iadd r4.xyz, r1.xyzx, r3.xyzx + itof r4.xyz, r4.xyzx + dp3 r2.w, r4.xyzx, r4.xyzx + iadd r5.yz, r0.zzzz, l(0, 10, 11, 0) + ieq r6.xy, cb0[0].zzzz, l(95, 96, 0, 0) + if_nz r6.x + ige r0.z, icb[r5.y + 0].x, l(15) + and r0.z, r0.z, l(1) + movc r7.xyz, r2.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r8.xyz, r3.xyzx, l(0,0,0,0), l(1,1,1,0) + or r7.xyz, r0.zzzz, r7.xyzx + or r8.xyz, r0.zzzz, r8.xyzx + ieq r9.xyz, r2.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ieq r10.xyz, r3.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ishl r0.z, l(1), icb[r5.y + 0].x + iadd r0.z, r0.z, l(-1) + ishl r11.xyz, r2.xyzx, icb[r5.y + 0].x + ishl r12.xyz, r3.xyzx, icb[r5.y + 0].x + ishr r11.xyz, r11.xyzx, l(16) + ishr r12.xyz, r12.xyzx, l(16) + movc r9.xyz, r9.xyzx, r0.zzzz, r11.xyzx + movc r10.xyz, r10.xyzx, r0.zzzz, r12.xyzx + movc r7.xyz, r7.xyzx, r2.xyzx, r9.xyzx + movc r8.xyz, r8.xyzx, r3.xyzx, r10.xyzx + else + ige r0.z, icb[r5.y + 0].x, l(16) + and r0.z, r0.z, l(1) + movc r9.xyz, r2.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r10.xyz, r3.xyzx, l(0,0,0,0), l(1,1,1,0) + or r9.xyz, r0.zzzz, r9.xyzx + or r10.xyz, r0.zzzz, r10.xyzx + ige r11.xyz, r2.xyzx, l(0, 0, 0, 0) + ige r12.xyz, r3.xyzx, l(0, 0, 0, 0) + ieq r13.xyz, r2.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r14.xyz, r3.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r0.z, l(-1), icb[r5.y + 0].x + ishl r3.w, l(1), r0.z + iadd r4.w, r3.w, l(-1) + ishl r15.xyz, r2.xyzx, r0.z + ishl r16.xyz, r3.xyzx, r0.z + ishr r15.xyz, r15.xyzx, l(15) + ishr r16.xyz, r16.xyzx, l(15) + movc r13.xyz, r13.xyzx, r4.wwww, r15.xyzx + movc r14.xyz, r14.xyzx, r4.wwww, r16.xyzx + ineg r15.xyz, r3.xyzx + ieq r16.xyz, r1.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r17.xyz, r15.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r3.w, -r3.w, l(1) + ishl r18.xyz, r1.xyzx, r0.z + ishl r15.xyz, r15.xyzx, r0.z + ishr r18.xyz, r18.xyzx, l(15) + ishr r15.xyz, r15.xyzx, l(15) + ineg r18.xyz, r18.xyzx + ineg r15.xyz, r15.xyzx + movc r16.xyz, r16.xyzx, r3.wwww, r18.xyzx + movc r15.xyz, r17.xyzx, r3.wwww, r15.xyzx + movc r11.xyz, r11.xyzx, r13.xyzx, r16.xyzx + movc r12.xyz, r12.xyzx, r14.xyzx, r15.xyzx + movc r7.xyz, r9.xyzx, r2.xyzx, r11.xyzx + movc r8.xyz, r10.xyzx, r3.xyzx, r12.xyzx + endif + iadd r2.xyz, -r7.xyzx, r8.xyzx + movc r2.xyz, icb[r5.y + 14].xxxx, r2.xyzx, r8.xyzx + ige r3.xyz, r2.xyzx, l(0, 0, 0, 0) + iadd r8.xyzw, l(-1, -1, -1, -1), icb[r5.y + 0].xyzw + ishl r9.x, l(1), r8.x + ishl r9.y, l(1), r8.y + ishl r9.z, l(1), r8.z + ishl r9.w, l(1), r8.w + ige r8.yzw, r2.xxyz, r9.yyzw + ineg r10.xyz, r2.xyzx + ilt r10.xyz, r9.yzwy, r10.xyzx + movc r11.xyz, r3.xyzx, r8.yzwy, r10.xyzx + or r0.z, r11.y, r11.x + or r11.x, r11.z, r0.z + ishl r12.x, l(1), icb[r5.y + 0].x + ishl r12.y, l(1), icb[r5.y + 0].y + ishl r12.z, l(1), icb[r5.y + 0].z + ishl r12.w, l(1), icb[r5.y + 0].w + iadd r12.xyzw, r12.xyzw, l(-1, -1, -1, -1) + and r7.xyz, r7.xyzx, r12.xxxx + iadd r13.xyzw, r9.yzwx, l(-1, -1, -1, -1) + movc r8.yzw, r8.yyzw, r13.xxyz, r2.xxyz + and r12.yzw, r2.xxyz, r12.yyzw + movc r10.xyz, r10.xyzx, r9.yzwy, r12.yzwy + movc r11.yzw, r3.xxyz, r8.yyzw, r10.xxyz + and r3.yzw, r2.xxyz, r12.xxxx + mov r3.x, l(0) + movc r3.xyzw, icb[r5.y + 14].xxxx, r11.xyzw, r3.xyzw + and r2.xyz, r9.xxxx, r7.xyzx + and r8.yzw, r7.xxyz, r13.wwww + iadd r8.yzw, -r9.xxxx, r8.yyzw + movc r2.xyz, r2.xyzx, r8.yzwy, r7.xyzx + movc r2.xyz, r6.yyyy, r2.xyzx, r7.xyzx + or r0.z, r6.y, icb[r5.y + 14].x + and r6.yzw, r9.yyzw, r3.yyzw + and r7.xyz, r13.xyzx, r3.yzwy + iadd r7.xyz, -r9.yzwy, r7.xyzx + movc r6.yzw, r6.yyzw, r7.xxyz, r3.yyzw + movc r3.yzw, r0.zzzz, r6.yyzw, r3.yyzw + iadd r6.yzw, r2.xxyz, r3.yyzw + movc r3.yzw, icb[r5.y + 14].xxxx, r6.yyzw, r3.yyzw + ult r6.yz, icb[r5.y + 0].xxxx, l(0, 15, 16, 0) + ieq r7.xyz, r12.xxxx, r2.xyzx + ieq r8.yzw, r12.xxxx, r3.yyzw + ishl r9.xyz, r2.xyzx, l(16) + ishl r10.xyz, r3.yzwy, l(16) + iadd r9.xyz, r9.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + iadd r10.xyz, r10.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + ushr r9.xyz, r9.xyzx, icb[r5.y + 0].x + ushr r10.xyz, r10.xyzx, icb[r5.y + 0].x + movc r7.xyz, r7.xyzx, l(0x0000ffff,0x0000ffff,0x0000ffff,0), r9.xyzx + movc r8.yzw, r8.yyzw, l(0,0x0000ffff,0x0000ffff,0x0000ffff), r10.xxyz + movc r7.xyz, r2.xyzx, r7.xyzx, l(0,0,0,0) + movc r8.yzw, r3.yyzw, r8.yyzw, l(0,0,0,0) + movc r7.xyz, r6.yyyy, r7.xyzx, r2.xyzx + movc r8.yzw, r6.yyyy, r8.yyzw, r3.yyzw + ige r9.xyz, r2.xyzx, l(0, 0, 0, 0) + ige r10.xyz, r3.yzwy, l(0, 0, 0, 0) + imax r11.xyz, -r2.xyzx, r2.xyzx + imax r12.xyz, -r3.yzwy, r3.yzwy + ige r13.xyz, r11.xyzx, r13.wwww + ige r14.xyz, r12.xyzx, r13.wwww + ishl r15.xyz, r11.xyzx, l(15) + ishl r16.xyz, r12.xyzx, l(15) + iadd r15.xyz, r15.xyzx, l(0x00004000, 0x00004000, 0x00004000, 0) + iadd r16.xyz, r16.xyzx, l(0x00004000, 0x00004000, 0x00004000, 0) + ushr r15.xyz, r15.xyzx, r8.x + ushr r16.xyz, r16.xyzx, r8.x + movc r13.xyz, r13.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r15.xyzx + movc r14.xyz, r14.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r16.xyzx + movc r11.xyz, r11.xyzx, r13.xyzx, l(0,0,0,0) + movc r12.xyz, r12.xyzx, r14.xyzx, l(0,0,0,0) + ineg r13.xyz, r11.xyzx + ineg r14.xyz, r12.xyzx + movc r9.xyz, r9.xyzx, r11.xyzx, r13.xyzx + movc r10.xyz, r10.xyzx, r12.xyzx, r14.xyzx + movc r2.xyz, r6.zzzz, r9.xyzx, r2.xyzx + movc r3.yzw, r6.zzzz, r10.xxyz, r3.yyzw + movc r2.xyz, r6.xxxx, r7.xyzx, r2.xyzx + movc r3.yzw, r6.xxxx, r8.yyzw, r3.yyzw + ge r0.z, l(0.000000), r2.w + mov r4.w, l(0) + mov r5.y, l(0) + loop + uge r5.w, r5.y, l(16) + breakc_nz r5.w + iadd r5.w, r0.y, r5.y + ld_structured r7.xyz, r5.w, l(12), g0.xyzx + iadd r6.yzw, r1.xxyz, r7.xxyz + itof r6.yzw, r6.yyzw + dp3 r6.y, r4.xyzx, r6.yzwy + ge r6.z, l(0.000000), r6.y + or r6.z, r0.z, r6.z + lt r6.w, r6.y, r2.w + mul r6.y, r6.y, l(63.499989) + div r6.y, r6.y, r2.w + ftou r6.y, r6.y + movc r6.y, r6.w, icb[r6.y + 14].y, l(15) + movc r6.y, r6.z, l(0), r6.y + iadd r6.z, l(64), -icb[r6.y + 14].z + imul null, r7.xyz, r3.yzwy, icb[r6.y + 14].zzzz + imad r6.yzw, r2.xxyz, r6.zzzz, r7.xxyz + iadd r6.yzw, r6.yyzw, l(0, 32, 32, 32) + ishr r6.yzw, r6.yyzw, l(6) + imul null, r7.xyz, r6.yzwy, l(31, 31, 31, 0) + ishr r8.xyz, r7.xyzx, l(6) + ilt r9.xyz, r6.yzwy, l(0, 0, 0, 0) + imul null, r6.yzw, r6.yyzw, l(0, -31, -31, -31) + ishr r6.yzw, r6.yyzw, l(5) + ineg r6.yzw, r6.yyzw + ishr r7.xyz, r7.xyzx, l(5) + movc r6.yzw, r9.xxyz, r6.yyzw, r7.xxyz + ilt r7.xyz, r6.yzwy, l(0, 0, 0, 0) + ineg r9.xyz, r6.yzwy + or r9.xyz, r9.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + movc r6.yzw, r7.xxyz, r9.xxyz, r6.yyzw + movc r6.yzw, r6.xxxx, r8.xxyz, r6.yyzw + and r7.xyzw, r6.yyzz, l(1023, 0x00007c00, 1023, 0x00007c00) + if_nz r7.y + ushr r7.y, r6.y, l(10) + and r7.y, r7.y, l(31) + else + if_nz r7.x + ishl r8.x, r7.x, l(1) + mov r8.y, r8.x + mov r7.y, l(0) + loop + and r8.z, r8.y, l(1024) + breakc_nz r8.z + iadd r7.y, r7.y, l(-1) + ishl r8.y, r8.y, l(1) + endloop + and r7.x, r8.y, l(1022) + else + mov r7.xy, l(0,-112,0,0) + endif + endif + ishl r8.xzw, r6.yyzw, l(16) + and r8.xzw, r8.xxzw, l(0x80000000, 0, 0x80000000, 0x80000000) + ishl r6.y, r7.y, l(23) + iadd r6.y, r6.y, l(0x38000000) + or r6.y, r6.y, r8.x + ishl r7.x, r7.x, l(13) + iadd r9.x, r6.y, r7.x + if_nz r7.w + ushr r6.y, r6.z, l(10) + and r6.y, r6.y, l(31) + else + if_nz r7.z + ishl r6.z, r7.z, l(1) + mov r7.x, r6.z + mov r6.y, l(0) + loop + and r7.w, r7.x, l(1024) + breakc_nz r7.w + iadd r6.y, r6.y, l(-1) + ishl r7.x, r7.x, l(1) + endloop + and r7.z, r7.x, l(1022) + else + mov r7.z, l(0) + mov r6.y, l(-112) + endif + endif + ishl r6.z, r6.y, l(23) + iadd r6.z, r6.z, l(0x38000000) + or r6.z, r6.z, r8.z + ishl r7.z, r7.z, l(13) + iadd r9.y, r6.z, r7.z + and r7.zw, r6.wwww, l(0, 0, 1023, 0x00007c00) + if_nz r7.w + ushr r6.z, r6.w, l(10) + and r6.z, r6.z, l(31) + else + if_nz r7.z + ishl r6.w, r7.z, l(1) + mov r7.w, r6.w + mov r6.z, l(0) + loop + and r8.x, r7.w, l(1024) + breakc_nz r8.x + iadd r6.z, r6.z, l(-1) + ishl r7.w, r7.w, l(1) + endloop + and r7.z, r7.w, l(1022) + else + mov r7.z, l(0) + mov r6.z, l(-112) + endif + endif + ishl r6.w, r6.z, l(23) + iadd r6.w, r6.w, l(0x38000000) + or r6.w, r6.w, r8.w + ishl r7.z, r7.z, l(13) + iadd r9.z, r6.w, r7.z + ld_structured r10.xyz, r5.w, l(24), g0.xyzx + add r8.xzw, r9.xxyz, -r10.xxyz + dp3 r5.w, r8.xzwx, r8.xzwx + add r4.w, r4.w, r5.w + iadd r5.y, r5.y, l(1) + endloop + movc r5.x, r3.x, l(100000002004087730000.000000), r4.w + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(40), r5.xzxx +endif +sync_g_t +if_nz r1.w + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(2) + ld_structured r2.yz, r0.y, l(40), g0.xxyx + lt r0.z, r2.y, r1.x + if_nz r0.z + ld_structured r2.x, r0.y, l(40), g0.xxxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(40), r2.xzxx + endif +endif +sync_g_t +if_nz r0.w + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(1) + ld_structured r2.yz, r0.y, l(40), g0.xxyx + lt r0.z, r2.y, r1.x + if_nz r0.z + ld_structured r2.x, r0.y, l(40), g0.xxxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(40), r2.xzxx + endif + ld_structured r1.xy, vThreadIDInGroupFlattened.x, l(40), g0.xyxx + mov r1.zw, l(0,0,0,0) + store_structured u0.xyzw, r0.x, l(0), r1.xyzw +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC6HEncode_TryModeG10CS[] = +{ + 68, 88, 66, 67, 117, 150, + 86, 154, 76, 44, 62, 174, + 101, 82, 50, 59, 75, 244, + 89, 47, 1, 0, 0, 0, + 84, 63, 0, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 0, 63, 0, 0, + 64, 0, 5, 0, 192, 15, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 58, 1, + 0, 0, 10, 0, 0, 0, + 5, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 7, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 11, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 11, 0, 0, 0, + 4, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 11, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 9, 0, + 0, 0, 5, 0, 0, 0, + 5, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 6, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 5, 0, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, + 10, 0, 0, 0, 11, 0, + 0, 0, 9, 0, 0, 0, + 9, 0, 0, 0, 9, 0, + 0, 0, 12, 0, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 13, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 1, 0, + 0, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 26, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 2, 0, 0, 0, 30, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 2, 0, + 0, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 43, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 2, 0, + 0, 0, 47, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 3, 0, 0, 0, + 51, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 3, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 64, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 158, 0, + 0, 4, 0, 224, 17, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 95, 0, 0, 2, + 0, 64, 2, 0, 95, 0, + 0, 2, 18, 16, 2, 0, + 104, 0, 0, 2, 19, 0, + 0, 0, 160, 0, 0, 5, + 0, 240, 17, 0, 0, 0, + 0, 0, 84, 0, 0, 0, + 64, 0, 0, 0, 155, 0, + 0, 4, 64, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 6, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 30, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 48, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 79, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 16, 0, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 78, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 0, 208, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 35, 0, + 0, 11, 18, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 26, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 4, 0, + 0, 0, 6, 5, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 127, + 255, 255, 127, 0, 255, 255, + 255, 127, 255, 255, 127, 0, + 79, 0, 0, 10, 50, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 255, 239, + 255, 71, 255, 239, 255, 71, + 0, 0, 0, 0, 0, 0, + 0, 0, 134, 0, 16, 0, + 4, 0, 0, 0, 79, 0, + 0, 10, 50, 0, 16, 0, + 5, 0, 0, 0, 134, 0, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 56, 0, 0, 128, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 194, 0, 16, 0, 5, 0, + 0, 0, 6, 8, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 30, 0, 0, 11, 194, 0, + 16, 0, 5, 0, 0, 0, + 166, 14, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 113, 0, 0, 0, 113, 0, + 0, 0, 30, 0, 0, 10, + 162, 0, 16, 0, 4, 0, + 0, 0, 86, 13, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 128, 0, 0, 0, + 0, 0, 0, 0, 128, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 85, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 10, + 50, 0, 16, 0, 4, 0, + 0, 0, 134, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 200, + 0, 0, 0, 200, 0, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 4, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 4, 0, 0, 0, + 30, 0, 0, 10, 194, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 15, 0, 0, + 255, 15, 0, 0, 85, 0, + 0, 7, 50, 0, 16, 0, + 4, 0, 0, 0, 70, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 10, + 50, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 50, 0, + 16, 0, 4, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 4, 0, 0, 0, 85, 0, + 0, 7, 50, 0, 16, 0, + 4, 0, 0, 0, 70, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 10, + 50, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 12, 50, 0, + 16, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 4, 0, 0, 0, + 30, 0, 0, 7, 50, 0, + 16, 0, 4, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 10, 50, 0, 16, 0, + 2, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 127, 255, 255, 127, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 239, 255, 71, 10, 0, + 16, 0, 2, 0, 0, 0, + 79, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 56, 85, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 8, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 113, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 200, 55, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 255, 15, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 127, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 127, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 6, 5, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 255, 3, 0, 0, + 0, 124, 0, 0, 255, 3, + 0, 0, 0, 124, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 18, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 1, + 1, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 4, 0, 0, 3, 0, + 4, 3, 10, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 1, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 254, 3, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 144, 255, 255, 255, 21, 0, + 0, 1, 21, 0, 0, 1, + 41, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 56, 60, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 1, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 4, + 0, 0, 3, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 41, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 1, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 254, 3, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 66, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 144, 255, + 255, 255, 21, 0, 0, 1, + 21, 0, 0, 1, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 50, 0, + 16, 0, 2, 0, 0, 0, + 166, 10, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 3, 0, 0, 0, 124, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 10, 0, 16, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 1, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 4, + 0, 0, 3, 0, 4, 3, + 42, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 1, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 254, 3, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 18, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 144, 255, + 255, 255, 21, 0, 0, 1, + 21, 0, 0, 1, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 16, 0, 0, 10, + 130, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 208, 179, 89, 62, + 89, 23, 55, 63, 152, 221, + 147, 61, 0, 0, 0, 0, + 32, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 95, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 78, 0, 0, 11, 114, 0, + 16, 0, 3, 0, 0, 0, + 0, 208, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 31, 0, 0, 0, 0, 0, + 0, 0, 79, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 123, 0, 0, 255, 123, + 0, 0, 255, 123, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 78, 0, 0, 11, + 114, 0, 16, 0, 7, 0, + 0, 0, 0, 208, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 224, 255, + 15, 0, 224, 255, 15, 0, + 224, 255, 15, 0, 0, 0, + 0, 0, 78, 0, 0, 11, + 114, 0, 16, 0, 4, 0, + 0, 0, 0, 208, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 1, 128, 255, 255, 1, 128, + 255, 255, 1, 128, 255, 255, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 150, 15, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 190, 24, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 114, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 167, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 190, 24, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 114, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 167, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 190, 24, + 0, 1, 31, 0, 4, 3, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 114, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 167, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 80, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 190, 24, + 0, 1, 79, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 76, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 76, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 80, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 190, 24, + 0, 1, 31, 0, 0, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 43, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 16, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 8, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 43, 0, 0, 5, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 49, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 29, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 56, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 14, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 28, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 79, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 150, 5, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 43, 0, 0, 5, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 30, 0, 0, 10, 98, 0, + 16, 0, 5, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 11, 50, 0, 16, 0, + 6, 0, 0, 0, 166, 138, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 95, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 6, 0, 0, 0, + 33, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 144, 144, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 144, 144, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 41, 0, + 0, 8, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 10, 144, 144, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 41, 0, 0, 8, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 10, 144, 144, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 18, 0, + 0, 1, 33, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 144, 144, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 9, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 10, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 10, 144, + 144, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 41, 0, 0, 7, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 17, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 246, 15, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 18, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 246, 15, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 21, 0, 0, 1, 30, 0, + 0, 8, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 55, 0, 0, 11, 114, 0, + 16, 0, 2, 0, 0, 0, + 6, 144, 208, 0, 14, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 11, 242, 0, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 70, 158, 144, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 33, 0, 0, 7, 226, 0, + 16, 0, 8, 0, 0, 0, + 6, 9, 16, 0, 2, 0, + 0, 0, 86, 14, 16, 0, + 9, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 34, 0, 0, 7, 114, 0, + 16, 0, 10, 0, 0, 0, + 150, 7, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 150, 7, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 8, 18, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 144, 144, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 41, 0, 0, 8, + 34, 0, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 26, 144, + 144, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 41, 0, + 0, 8, 66, 0, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 144, 144, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 41, 0, 0, 8, 130, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 58, 144, 144, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 12, 0, + 0, 0, 70, 14, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 1, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 6, 0, 16, 0, + 12, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 13, 0, 0, 0, 150, 3, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 55, 0, 0, 9, + 226, 0, 16, 0, 8, 0, + 0, 0, 86, 14, 16, 0, + 8, 0, 0, 0, 6, 9, + 16, 0, 13, 0, 0, 0, + 6, 9, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 7, + 226, 0, 16, 0, 12, 0, + 0, 0, 6, 9, 16, 0, + 2, 0, 0, 0, 86, 14, + 16, 0, 12, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 150, 7, 16, 0, + 9, 0, 0, 0, 150, 7, + 16, 0, 12, 0, 0, 0, + 55, 0, 0, 9, 226, 0, + 16, 0, 11, 0, 0, 0, + 6, 9, 16, 0, 3, 0, + 0, 0, 86, 14, 16, 0, + 8, 0, 0, 0, 6, 9, + 16, 0, 10, 0, 0, 0, + 1, 0, 0, 7, 226, 0, + 16, 0, 3, 0, 0, 0, + 6, 9, 16, 0, 2, 0, + 0, 0, 6, 0, 16, 0, + 12, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 11, 242, 0, + 16, 0, 3, 0, 0, 0, + 6, 144, 208, 0, 14, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 11, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 6, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 1, 0, 0, 7, 226, 0, + 16, 0, 8, 0, 0, 0, + 6, 9, 16, 0, 7, 0, + 0, 0, 246, 15, 16, 0, + 13, 0, 0, 0, 30, 0, + 0, 8, 226, 0, 16, 0, + 8, 0, 0, 0, 6, 0, + 16, 128, 65, 0, 0, 0, + 9, 0, 0, 0, 86, 14, + 16, 0, 8, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 150, 7, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 60, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 10, 144, 208, 0, + 14, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 0, 0, 7, 226, 0, + 16, 0, 6, 0, 0, 0, + 86, 14, 16, 0, 9, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 150, 7, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 7, 0, + 0, 0, 150, 7, 16, 128, + 65, 0, 0, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 86, 14, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 7, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 226, 0, 16, 0, + 6, 0, 0, 0, 6, 9, + 16, 0, 2, 0, 0, 0, + 86, 14, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 11, + 226, 0, 16, 0, 3, 0, + 0, 0, 6, 144, 208, 0, + 14, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 79, 0, + 0, 11, 98, 0, 16, 0, + 6, 0, 0, 0, 6, 144, + 144, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 6, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 32, 0, + 0, 7, 226, 0, 16, 0, + 8, 0, 0, 0, 6, 0, + 16, 0, 12, 0, 0, 0, + 86, 14, 16, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 10, 0, 0, 0, + 150, 7, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 8, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 10, 144, 144, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 85, 0, 0, 8, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 10, 144, + 144, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 55, 0, + 0, 12, 226, 0, 16, 0, + 8, 0, 0, 0, 86, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 6, 9, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 226, 0, 16, 0, + 8, 0, 0, 0, 86, 14, + 16, 0, 3, 0, 0, 0, + 86, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 86, 5, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 8, 0, 0, 0, 86, 5, + 16, 0, 6, 0, 0, 0, + 86, 14, 16, 0, 8, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 10, 0, + 0, 0, 150, 7, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 36, 0, 0, 8, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 36, 0, 0, 8, + 114, 0, 16, 0, 12, 0, + 0, 0, 150, 7, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 150, 7, 16, 0, + 3, 0, 0, 0, 33, 0, + 0, 7, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 246, 15, 16, 0, 13, 0, + 0, 0, 33, 0, 0, 7, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 246, 15, + 16, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 166, 10, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 10, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 6, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 3, 0, 0, 0, 6, 0, + 16, 0, 6, 0, 0, 0, + 86, 14, 16, 0, 8, 0, + 0, 0, 86, 14, 16, 0, + 3, 0, 0, 0, 29, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 58, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 226, 0, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 1, 0, + 0, 0, 6, 9, 16, 0, + 7, 0, 0, 0, 43, 0, + 0, 5, 226, 0, 16, 0, + 6, 0, 0, 0, 86, 14, + 16, 0, 6, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 150, 7, 16, 0, + 6, 0, 0, 0, 29, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 49, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 14, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 28, 0, 0, 5, 34, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 55, 0, 0, 11, + 34, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 26, 144, + 208, 0, 14, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 10, 66, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 42, 144, 208, 128, 65, 0, + 0, 0, 14, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 38, 0, 0, 10, + 0, 208, 0, 0, 114, 0, + 16, 0, 7, 0, 0, 0, + 150, 7, 16, 0, 3, 0, + 0, 0, 166, 154, 208, 0, + 14, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 35, 0, 0, 9, 226, 0, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 6, 0, 0, 0, 6, 9, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 10, 226, 0, + 16, 0, 6, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, + 32, 0, 0, 0, 42, 0, + 0, 7, 226, 0, 16, 0, + 6, 0, 0, 0, 86, 14, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 114, 0, + 16, 0, 7, 0, 0, 0, + 150, 7, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 34, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 150, 7, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 38, 0, 0, 11, 0, 208, + 0, 0, 226, 0, 16, 0, + 6, 0, 0, 0, 86, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 225, 255, 255, 255, + 225, 255, 255, 255, 225, 255, + 255, 255, 42, 0, 0, 7, + 226, 0, 16, 0, 6, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 40, 0, 0, 5, 226, 0, + 16, 0, 6, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 226, 0, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 9, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 6, 9, + 16, 0, 7, 0, 0, 0, + 34, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 150, 7, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 9, 0, 0, 0, 150, 7, + 16, 0, 6, 0, 0, 0, + 60, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 6, 9, + 16, 0, 7, 0, 0, 0, + 6, 9, 16, 0, 9, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 8, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 86, 10, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 255, 3, + 0, 0, 0, 124, 0, 0, + 255, 3, 0, 0, 0, 124, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 7, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 18, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 8, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 1, 0, 0, 7, + 66, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 4, 0, 0, + 3, 0, 4, 3, 42, 0, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 41, 0, + 0, 7, 34, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 1, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 254, 3, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 8, + 50, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 144, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 41, 0, 0, 7, 210, 0, + 16, 0, 8, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 10, 210, 0, 16, 0, + 8, 0, 0, 0, 6, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 128, 0, 0, 0, 0, + 0, 0, 0, 128, 0, 0, + 0, 128, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 56, 60, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 7, 0, 0, 0, 85, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 1, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 0, 4, + 0, 0, 3, 0, 4, 3, + 58, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 41, 0, 0, 7, 18, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 1, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 254, 3, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 66, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 144, 255, + 255, 255, 21, 0, 0, 1, + 21, 0, 0, 1, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 7, 0, 0, 0, + 246, 15, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 3, 0, 0, + 0, 124, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 7, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 1, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 0, 4, + 0, 0, 3, 0, 4, 3, + 10, 0, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 41, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 1, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 254, 3, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 66, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 144, 255, + 255, 255, 21, 0, 0, 1, + 21, 0, 0, 1, 41, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 210, 0, + 16, 0, 8, 0, 0, 0, + 6, 9, 16, 0, 9, 0, + 0, 0, 6, 9, 16, 128, + 65, 0, 0, 0, 10, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 134, 3, 16, 0, + 8, 0, 0, 0, 134, 3, + 16, 0, 8, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 55, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 236, 120, 173, 96, 58, 0, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 134, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 58, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 98, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 241, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 134, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 98, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 241, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 134, 0, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 8, 50, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 0, + 0, 9, 242, 224, 17, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 62, 0, 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeG10CS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeG10CS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..63aab434e05e3221ffe111c6da6e088be9c37cc7 Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeG10CS.pdb differ diff --git a/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeLE10CS.inc b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeLE10CS.inc new file mode 100644 index 0000000000000000000000000000000000000000..5cac112c6ec7c5b8af5ae90cc910c563f0e38d01 --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeLE10CS.inc @@ -0,0 +1,5061 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { 0x0000cccc, 15, -1, 0}, + { 0x00008888, 15, -1, 9}, + { 0x0000eeee, 15, -1, 18}, + { 0x0000ecc8, 15, -1, 27}, + { 0x0000c880, 15, -1, 37}, + { 0x0000feec, 15, -1, 46}, + { 0x0000fec8, 15, -1, 55}, + { 0x0000ec80, 15, -1, 64}, + { 0x0000c800, 15, -1, 0}, + { 0x0000ffec, 15, 0, 0}, + { 0x0000fe80, 15, 0, 0}, + { 0x0000e800, 15, -1, 0}, + { 0x0000ffe8, 15, -1, 0}, + { 0x0000ff00, 15, -1, 0}, + { 0x0000fff0, 15, 0, 0}, + { 0x0000f000, 15, 0, 0}, + { 0x0000f710, 15, 0, 0}, + { 142, 2, 0, 0}, + { 0x00007100, 8, 0, 0}, + { 2254, 2, 0, 0}, + { 140, 2, 0, 0}, + { 0x00007310, 8, 0, 0}, + { 0x00003100, 8, 0, 0}, + { 0x00008cce, 15, 0, 0}, + { 2188, 2, 0, 0}, + { 0x00003110, 8, 0, 0}, + { 0x00006666, 2, 0, 0}, + { 0x0000366c, 2, 0, 0}, + { 6120, 8, 0, 0}, + { 4080, 8, 0, 0}, + { 0x0000718e, 2, 0, 0}, + { 0x0000399c, 2, 0, 0}, + { 10, 5, 5, 5}, + { 7, 6, 6, 6}, + { 11, 5, 4, 4}, + { 11, 4, 5, 4}, + { 11, 4, 4, 5}, + { 9, 5, 5, 5}, + { 8, 6, 5, 5}, + { 8, 5, 6, 5}, + { 8, 5, 5, 6}, + { 6, 6, 6, 6}, + { 10, 10, 10, 10}, + { 11, 9, 9, 9}, + { 12, 8, 8, 8}, + { 16, 4, 4, 4}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_structured t1, 16 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 24 +dcl_indexableTemp x0[6], 4 +dcl_indexableTemp x1[2], 4 +dcl_tgsm_structured g0, 84, 64 +dcl_thread_group 64, 1, 1 +ushr r0.x, vThreadIDInGroupFlattened.x, l(5) +ishl r0.y, vThreadGroupID.x, l(1) +iadd r0.y, r0.y, cb0[1].x +iadd r0.x, r0.x, r0.y +and r0.y, vThreadIDInGroupFlattened.x, l(32) +iadd r1.z, -r0.y, vThreadIDInGroupFlattened.x +ult r2.xyzw, r1.zzzz, l(16, 32, 8, 4) +if_nz r2.x + udiv r0.z, null, r0.x, cb0[0].y + imad r0.w, -r0.z, cb0[0].y, r0.x + ishl r0.w, r0.w, l(2) + ishl r0.z, r0.z, l(2) + and r1.w, r1.z, l(3) + iadd r3.x, r0.w, r1.w + ushr r0.w, r1.z, l(2) + iadd r3.y, r0.w, r0.z + mov r3.zw, l(0,0,0,0) + ld r3.xyzw, r3.xyzw, t0.xyzw + ushr r4.xyz, r3.xyzx, l(16) + and r4.xyz, r4.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + and r5.xyzw, r3.xxyy, l(0x7fffffff, 0x007fffff, 0x7fffffff, 0x007fffff) + ult r0.zw, l(0, 0, 0x47ffefff, 0x47ffefff), r5.xxxz + ult r3.xy, r5.xzxx, l(0x38800000, 0x38800000, 0, 0) + ushr r6.xy, r5.xzxx, l(23) + iadd r6.xy, -r6.xyxx, l(113, 113, 0, 0) + iadd r5.yw, r5.yyyw, l(0, 0x00800000, 0, 0x00800000) + ushr r7.x, r5.y, r6.x + ushr r7.y, r5.w, r6.y + iadd r5.xy, r5.xzxx, l(0xc8000000, 0xc8000000, 0, 0) + movc r3.xy, r3.xyxx, r7.xyxx, r5.xyxx + iadd r5.xy, r3.xyxx, l(4095, 4095, 0, 0) + ushr r3.xy, r3.xyxx, l(13) + and r3.xy, r3.xyxx, l(1, 1, 0, 0) + iadd r3.xy, r3.xyxx, r5.xyxx + ushr r3.xy, r3.xyxx, l(13) + and r3.xy, r3.xyxx, l(0x00007fff, 0x00007fff, 0, 0) + movc r0.zw, r0.zzzw, l(0,0,0x00007fff,0x00007fff), r3.xxxy + iadd r5.xy, r4.xyxx, r0.zwzz + and r0.zw, r3.zzzz, l(0, 0, 0x7fffffff, 0x007fffff) + ult r1.w, l(0x47ffefff), r0.z + ult r3.x, r0.z, l(0x38800000) + ushr r3.y, r0.z, l(23) + iadd r3.y, -r3.y, l(113) + iadd r0.w, r0.w, l(0x00800000) + ushr r0.w, r0.w, r3.y + iadd r0.z, r0.z, l(0xc8000000) + movc r0.z, r3.x, r0.w, r0.z + iadd r0.w, r0.z, l(4095) + ushr r0.z, r0.z, l(13) + and r0.z, r0.z, l(1) + iadd r0.z, r0.z, r0.w + ushr r0.z, r0.z, l(13) + and r0.z, r0.z, l(0x00007fff) + movc r0.z, r1.w, l(0x00007fff), r0.z + iadd r5.z, r4.z, r0.z + and r3.xyzw, r5.xxyy, l(1023, 0x00007c00, 1023, 0x00007c00) + if_nz r3.y + ushr r0.z, r5.x, l(10) + and r0.z, r0.z, l(31) + else + if_nz r3.x + ishl r0.w, r3.x, l(1) + mov r1.w, r0.w + mov r0.z, l(0) + loop + and r3.y, r1.w, l(1024) + breakc_nz r3.y + iadd r0.z, r0.z, l(-1) + ishl r1.w, r1.w, l(1) + endloop + and r3.x, r1.w, l(1022) + else + mov r3.x, l(0) + mov r0.z, l(-112) + endif + endif + ishl r4.xyz, r5.xyzx, l(16) + and r4.xyz, r4.xyzx, l(0x80000000, 0x80000000, 0x80000000, 0) + ishl r0.z, r0.z, l(23) + iadd r0.z, r0.z, l(0x38000000) + or r0.z, r0.z, r4.x + ishl r0.w, r3.x, l(13) + iadd r6.x, r0.w, r0.z + if_nz r3.w + ushr r0.z, r5.y, l(10) + and r0.z, r0.z, l(31) + else + if_nz r3.z + ishl r0.w, r3.z, l(1) + mov r1.w, r0.w + mov r0.z, l(0) + loop + and r3.x, r1.w, l(1024) + breakc_nz r3.x + iadd r0.z, r0.z, l(-1) + ishl r1.w, r1.w, l(1) + endloop + and r3.z, r1.w, l(1022) + else + mov r3.z, l(0) + mov r0.z, l(-112) + endif + endif + ishl r0.z, r0.z, l(23) + iadd r0.z, r0.z, l(0x38000000) + or r0.z, r0.z, r4.y + ishl r0.w, r3.z, l(13) + iadd r6.y, r0.w, r0.z + and r0.zw, r5.zzzz, l(0, 0, 1023, 0x00007c00) + if_nz r0.w + ushr r0.w, r5.z, l(10) + and r0.w, r0.w, l(31) + else + if_nz r0.z + ishl r1.w, r0.z, l(1) + mov r3.x, r1.w + mov r0.w, l(0) + loop + and r3.y, r3.x, l(1024) + breakc_nz r3.y + iadd r0.w, r0.w, l(-1) + ishl r3.x, r3.x, l(1) + endloop + and r0.z, r3.x, l(1022) + else + mov r0.zw, l(0,0,0,-112) + endif + endif + ishl r0.w, r0.w, l(23) + iadd r0.w, r0.w, l(0x38000000) + or r0.w, r0.w, r4.z + ishl r0.z, r0.z, l(13) + iadd r6.z, r0.z, r0.w + dp3 r6.w, r6.xyzx, l(0.212600, 0.715200, 0.072200, 0.000000) + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(24), r6.xyzw + ieq r0.z, cb0[0].z, l(95) + ishl r3.xyz, r5.xyzx, l(6) + udiv r3.xyz, null, r3.xyzx, l(31, 31, 31, 0) + ult r4.xyz, r5.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + ieq r6.xyz, r5.xyzx, l(0x00007bff, 0x00007bff, 0x00007bff, 0) + ishl r5.xyz, r5.xyzx, l(5) + udiv r7.xyz, null, r5.xyzx, l(31, 31, 31, 0) + movc r7.xyz, r6.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r7.xyzx + and r5.xyz, r5.xyzx, l(0x000fffe0, 0x000fffe0, 0x000fffe0, 0) + udiv r5.xyz, null, r5.xyzx, l(31, 31, 31, 0) + ineg r5.xyz, r5.xyzx + movc r5.xyz, r6.xyzx, l(0xffff8001,0xffff8001,0xffff8001,0), r5.xyzx + movc r4.xyz, r4.xyzx, r7.xyzx, r5.xyzx + movc r3.xyz, r0.zzzz, r3.xyzx, r4.xyzx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(12), r3.xyzx +endif +sync_g_t +if_nz r2.y + mov x0[0].x, l(0x7fffffff) + mov x0[1].x, l(0x7fffffff) + mov x0[2].x, l(0x7fffffff) + mov x0[0].y, l(-0.000000) + mov x0[1].y, l(-0.000000) + mov x0[2].y, l(-0.000000) + mov x0[3].x, l(0x7fffffff) + mov x0[4].x, l(0x7fffffff) + mov x0[5].x, l(0x7fffffff) + mov x0[3].y, l(-0.000000) + mov x0[4].y, l(-0.000000) + mov x0[5].y, l(-0.000000) + mov x1[0].x, l(340282346638528860000000000000000000000.000000) + mov x1[0].y, l(-340282346638528860000000000000000000000.000000) + mov x1[1].x, l(340282346638528860000000000000000000000.000000) + mov x1[1].y, l(-340282346638528860000000000000000000000.000000) + mov r0.z, l(0) + loop + uge r0.w, r0.z, l(16) + breakc_nz r0.w + iadd r0.w, r0.z, r0.y + ld_structured r3.xyz, r0.w, l(12), g0.xyzx + ld_structured r4.x, r0.w, l(36), g0.xxxx + ushr r0.w, icb[r1.z + 0].x, r0.z + and r0.w, r0.w, l(1) + if_nz r0.w + mov r0.w, x1[1].x + lt r1.w, r4.x, r0.w + mov r2.y, x0[3].x + movc r2.y, r1.w, r3.x, r2.y + mov x0[3].x, r2.y + mov r2.y, x0[4].x + movc r2.y, r1.w, r3.y, r2.y + mov x0[4].x, r2.y + mov r2.y, x0[5].x + movc r2.y, r1.w, r3.z, r2.y + mov x0[5].x, r2.y + movc r0.w, r1.w, r4.x, r0.w + mov x1[1].x, r0.w + mov r0.w, x1[1].y + lt r1.w, r0.w, r4.x + mov r2.y, x0[3].y + movc r2.y, r1.w, r3.x, r2.y + mov x0[3].y, r2.y + mov r2.y, x0[4].y + movc r2.y, r1.w, r3.y, r2.y + mov x0[4].y, r2.y + mov r2.y, x0[5].y + movc r2.y, r1.w, r3.z, r2.y + mov x0[5].y, r2.y + movc r0.w, r1.w, r4.x, r0.w + mov x1[1].y, r0.w + else + mov r0.w, x1[0].x + lt r1.w, r4.x, r0.w + mov r2.y, x0[0].x + movc r2.y, r1.w, r3.x, r2.y + mov x0[0].x, r2.y + mov r2.y, x0[1].x + movc r2.y, r1.w, r3.y, r2.y + mov x0[1].x, r2.y + mov r2.y, x0[2].x + movc r2.y, r1.w, r3.z, r2.y + mov x0[2].x, r2.y + movc r0.w, r1.w, r4.x, r0.w + mov x1[0].x, r0.w + mov r0.w, x1[0].y + lt r1.w, r0.w, r4.x + mov r2.y, x0[0].y + movc r2.y, r1.w, r3.x, r2.y + mov x0[0].y, r2.y + mov r2.y, x0[1].y + movc r2.y, r1.w, r3.y, r2.y + mov x0[1].y, r2.y + mov r2.y, x0[2].y + movc r2.y, r1.w, r3.z, r2.y + mov x0[2].y, r2.y + movc r0.w, r1.w, r4.x, r0.w + mov x1[0].y, r0.w + endif + iadd r0.z, r0.z, l(1) + endloop + mov r3.x, x0[0].y + mov r3.y, x0[1].y + mov r3.z, x0[2].y + mov r0.z, x0[0].x + mov r0.w, x0[1].x + mov r1.w, x0[2].x + ineg r4.xy, r0.zwzz + ineg r4.z, r1.w + iadd r5.xyz, r3.xyzx, r4.xyzx + itof r5.xyz, r5.xyzx + dp3 r2.y, r5.xyzx, r5.xyzx + ld_structured r6.xyz, r0.y, l(12), g0.xyzx + iadd r4.xyz, r4.xyzx, r6.xyzx + itof r4.xyz, r4.xyzx + dp3 r3.w, r5.xyzx, r4.xyzx + lt r4.x, l(0.000000), r2.y + ge r4.y, r3.w, l(0.000000) + and r4.x, r4.y, r4.x + mul r3.w, r3.w, l(63.499989) + div r3.w, r3.w, r2.y + ftou r3.w, r3.w + ult r3.w, l(32), r3.w + and r3.w, r3.w, r4.x + movc r4.xyz, r3.wwww, -r5.xyzx, r5.xyzx + movc r5.xy, r3.wwww, r3.xyxx, r0.zwzz + movc r5.z, r3.w, r3.z, r1.w + movc r6.xy, r3.wwww, r0.zwzz, r3.xyxx + movc r6.z, r3.w, r1.w, r3.z + mov r3.x, x0[3].y + mov r3.y, x0[4].y + mov r3.z, x0[5].y + mov r0.z, x0[3].x + mov r0.w, x0[4].x + mov r1.w, x0[5].x + ineg r7.xy, r0.zwzz + ineg r7.z, r1.w + iadd r8.xyz, r3.xyzx, r7.xyzx + itof r8.xyz, r8.xyzx + dp3 r3.w, r8.xyzx, r8.xyzx + iadd r4.w, r0.y, icb[r1.z + 0].y + ld_structured r9.xyz, r4.w, l(12), g0.xyzx + iadd r7.xyz, r7.xyzx, r9.xyzx + itof r7.xyz, r7.xyzx + dp3 r4.w, r8.xyzx, r7.xyzx + lt r5.w, l(0.000000), r3.w + ge r6.w, r4.w, l(0.000000) + and r5.w, r5.w, r6.w + mul r4.w, r4.w, l(63.499989) + div r4.w, r4.w, r3.w + ftou r4.w, r4.w + ult r4.w, l(32), r4.w + and r4.w, r4.w, r5.w + movc r7.xyz, r4.wwww, -r8.xyzx, r8.xyzx + movc r8.xy, r4.wwww, r3.xyxx, r0.zwzz + movc r8.z, r4.w, r3.z, r1.w + movc r9.xy, r4.wwww, r0.zwzz, r3.xyxx + movc r9.z, r4.w, r1.w, r3.z + ieq r0.zw, cb0[0].zzzz, l(0, 0, 95, 96) + if_nz r0.z + mov r1.w, cb0[0].w + ige r3.x, icb[r1.w + 32].x, l(15) + and r3.x, r3.x, l(1) + movc r10.xyz, r5.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r11.xyz, r6.xyzx, l(0,0,0,0), l(1,1,1,0) + or r10.xyz, r3.xxxx, r10.xyzx + or r11.xyz, r3.xxxx, r11.xyzx + ieq r12.xyz, r5.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ieq r13.xyz, r6.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ishl r3.y, l(1), icb[r1.w + 32].x + iadd r3.y, r3.y, l(-1) + ishl r14.xyz, r5.xyzx, icb[r1.w + 32].x + ishl r15.xyz, r6.xyzx, icb[r1.w + 32].x + ishr r14.xyz, r14.xyzx, l(16) + ishr r15.xyz, r15.xyzx, l(16) + movc r12.xyz, r12.xyzx, r3.yyyy, r14.xyzx + movc r13.xyz, r13.xyzx, r3.yyyy, r15.xyzx + movc r10.xyz, r10.xyzx, r5.xyzx, r12.xyzx + movc r11.xyz, r11.xyzx, r6.xyzx, r13.xyzx + movc r12.xyz, r8.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r13.xyz, r9.xyzx, l(0,0,0,0), l(1,1,1,0) + or r12.xyz, r3.xxxx, r12.xyzx + or r13.xyz, r3.xxxx, r13.xyzx + ieq r14.xyz, r8.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + ieq r15.xyz, r9.xyzx, l(0x0000ffff, 0x0000ffff, 0x0000ffff, 0) + mov r1.w, cb0[0].w + ishl r16.xyz, r8.xyzx, icb[r1.w + 32].x + ishl r17.xyz, r9.xyzx, icb[r1.w + 32].x + ishr r16.xyz, r16.xyzx, l(16) + ishr r17.xyz, r17.xyzx, l(16) + movc r14.xyz, r14.xyzx, r3.yyyy, r16.xyzx + movc r3.xyz, r15.xyzx, r3.yyyy, r17.xyzx + movc r12.xyz, r12.xyzx, r8.xyzx, r14.xyzx + movc r3.xyz, r13.xyzx, r9.xyzx, r3.xyzx + else + mov r1.w, cb0[0].w + ige r4.w, icb[r1.w + 32].x, l(16) + and r4.w, r4.w, l(1) + movc r13.xyz, r5.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r14.xyz, r6.xyzx, l(0,0,0,0), l(1,1,1,0) + or r13.xyz, r4.wwww, r13.xyzx + or r14.xyz, r4.wwww, r14.xyzx + ige r15.xyz, r5.xyzx, l(0, 0, 0, 0) + ige r16.xyz, r6.xyzx, l(0, 0, 0, 0) + ieq r17.xyz, r5.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r18.xyz, r6.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r1.w, l(-1), icb[r1.w + 32].x + ishl r5.w, l(1), r1.w + iadd r6.w, r5.w, l(-1) + ishl r19.xyz, r5.xyzx, r1.w + ishl r20.xyz, r6.xyzx, r1.w + ishr r19.xyz, r19.xyzx, l(15) + ishr r20.xyz, r20.xyzx, l(15) + movc r17.xyz, r17.xyzx, r6.wwww, r19.xyzx + movc r18.xyz, r18.xyzx, r6.wwww, r20.xyzx + ineg r19.xyz, r5.xyzx + ineg r20.xyz, r6.xyzx + ieq r21.xyz, r19.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r22.xyz, r20.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + iadd r5.w, -r5.w, l(1) + ishl r19.xyz, r19.xyzx, r1.w + ishl r20.xyz, r20.xyzx, r1.w + ishr r19.xyz, r19.xyzx, l(15) + ishr r20.xyz, r20.xyzx, l(15) + ineg r19.xyz, r19.xyzx + ineg r20.xyz, r20.xyzx + movc r19.xyz, r21.xyzx, r5.wwww, r19.xyzx + movc r20.xyz, r22.xyzx, r5.wwww, r20.xyzx + movc r15.xyz, r15.xyzx, r17.xyzx, r19.xyzx + movc r16.xyz, r16.xyzx, r18.xyzx, r20.xyzx + movc r10.xyz, r13.xyzx, r5.xyzx, r15.xyzx + movc r11.xyz, r14.xyzx, r6.xyzx, r16.xyzx + movc r6.xyz, r8.xyzx, l(0,0,0,0), l(1,1,1,0) + movc r13.xyz, r9.xyzx, l(0,0,0,0), l(1,1,1,0) + or r6.xyz, r4.wwww, r6.xyzx + or r13.xyz, r4.wwww, r13.xyzx + ige r14.xyz, r8.xyzx, l(0, 0, 0, 0) + ige r15.xyz, r9.xyzx, l(0, 0, 0, 0) + ieq r16.xyz, r8.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r17.xyz, r9.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ishl r18.xyz, r8.xyzx, r1.w + ishl r19.xyz, r9.xyzx, r1.w + ishr r18.xyz, r18.xyzx, l(15) + ishr r19.xyz, r19.xyzx, l(15) + movc r16.xyz, r16.xyzx, r6.wwww, r18.xyzx + movc r17.xyz, r17.xyzx, r6.wwww, r19.xyzx + ineg r18.xyz, r8.xyzx + ineg r19.xyz, r9.xyzx + ieq r20.xyz, r18.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ieq r21.xyz, r19.xyzx, l(0x00007fff, 0x00007fff, 0x00007fff, 0) + ishl r18.xyz, r18.xyzx, r1.w + ishl r19.xyz, r19.xyzx, r1.w + ishr r18.xyz, r18.xyzx, l(15) + ishr r19.xyz, r19.xyzx, l(15) + ineg r18.xyz, r18.xyzx + ineg r19.xyz, r19.xyzx + movc r18.xyz, r20.xyzx, r5.wwww, r18.xyzx + movc r19.xyz, r21.xyzx, r5.wwww, r19.xyzx + movc r14.xyz, r14.xyzx, r16.xyzx, r18.xyzx + movc r15.xyz, r15.xyzx, r17.xyzx, r19.xyzx + movc r12.xyz, r6.xyzx, r8.xyzx, r14.xyzx + movc r3.xyz, r13.xyzx, r9.xyzx, r15.xyzx + endif + iadd r6.xyz, -r10.xyzx, r11.xyzx + mov r1.w, cb0[0].w + movc r6.xyz, icb[r1.w + 0].zzzz, r6.xyzx, r11.xyzx + iadd r9.xyz, -r10.xyzx, r12.xyzx + movc r9.xyz, icb[r1.w + 0].zzzz, r9.xyzx, r12.xyzx + iadd r11.xyz, -r10.xyzx, r3.xyzx + movc r3.xyz, icb[r1.w + 0].zzzz, r11.xyzx, r3.xyzx + if_nz icb[r1.w + 0].z + ige r11.xyz, r6.xyzx, l(0, 0, 0, 0) + iadd r12.xyz, l(-1, -1, -1, 0), icb[r1.w + 32].yzwy + ishl r13.x, l(1), r12.x + ishl r13.y, l(1), r12.y + ishl r13.z, l(1), r12.z + ige r12.xyz, r6.xyzx, r13.xyzx + ineg r14.xyz, r6.xyzx + ilt r14.xyz, r13.xyzx, r14.xyzx + movc r15.xyz, r11.xyzx, r12.xyzx, r14.xyzx + or r4.w, r15.y, r15.x + or r4.w, r15.z, r4.w + ishl r15.x, l(1), icb[r1.w + 32].x + ishl r15.y, l(1), icb[r1.w + 32].y + ishl r15.z, l(1), icb[r1.w + 32].z + ishl r15.w, l(1), icb[r1.w + 32].w + iadd r15.xyzw, r15.xyzw, l(-1, -1, -1, -1) + and r16.xyz, r10.xyzx, r15.xxxx + iadd r17.xyz, r13.xyzx, l(-1, -1, -1, 0) + movc r12.xyz, r12.xyzx, r17.xyzx, r6.xyzx + and r18.xyz, r6.xyzx, r15.yzwy + movc r14.xyz, r14.xyzx, r13.xyzx, r18.xyzx + movc r11.xyz, r11.xyzx, r12.xyzx, r14.xyzx + ige r12.xyz, r9.xyzx, l(0, 0, 0, 0) + ige r14.xyz, r9.xyzx, r13.xyzx + ineg r18.xyz, r9.xyzx + ilt r18.xyz, r13.xyzx, r18.xyzx + movc r19.xyz, r12.xyzx, r14.xyzx, r18.xyzx + ige r20.xyz, r3.xyzx, l(0, 0, 0, 0) + ige r21.xyz, r3.xyzx, r13.xyzx + ineg r22.xyz, r3.xyzx + ilt r22.xyz, r13.xyzx, r22.xyzx + movc r23.xyz, r20.xyzx, r21.xyzx, r22.xyzx + or r19.xyz, r19.xyzx, r23.xyzx + or r5.w, r19.y, r19.x + or r5.w, r19.z, r5.w + or r4.w, r4.w, r5.w + and r4.w, r4.w, l(1) + movc r14.xyz, r14.xyzx, r17.xyzx, r9.xyzx + and r19.xyz, r9.xyzx, r15.yzwy + movc r18.xyz, r18.xyzx, r13.xyzx, r19.xyzx + movc r12.xyz, r12.xyzx, r14.xyzx, r18.xyzx + movc r14.xyz, r21.xyzx, r17.xyzx, r3.xyzx + and r15.xyz, r3.xyzx, r15.yzwy + movc r13.xyz, r22.xyzx, r13.xyzx, r15.xyzx + movc r13.xyz, r20.xyzx, r14.xyzx, r13.xyzx + else + ishl r5.w, l(1), icb[r1.w + 32].x + iadd r5.w, r5.w, l(-1) + and r16.xyz, r5.wwww, r10.xyzx + and r11.xyz, r5.wwww, r6.xyzx + and r12.xyz, r5.wwww, r9.xyzx + and r13.xyz, r3.xyzx, r5.wwww + mov r4.w, l(0) + endif + iadd r6.xyzw, l(-1, -1, -1, -1), icb[r1.w + 32].xyzw + ishl r9.x, l(1), r6.x + ishl r9.y, l(1), r6.y + ishl r9.z, l(1), r6.z + ishl r9.w, l(1), r6.w + and r3.xyz, r9.xxxx, r16.xyzx + iadd r10.xyzw, r9.xyzw, l(-1, -1, -1, -1) + and r6.yzw, r10.xxxx, r16.xxyz + iadd r6.yzw, -r9.xxxx, r6.yyzw + movc r3.xyz, r3.xyzx, r6.yzwy, r16.xyzx + movc r3.xyz, r0.wwww, r3.xyzx, r16.xyzx + or r0.w, r0.w, icb[r1.w + 0].z + and r6.yzw, r9.yyzw, r11.xxyz + and r14.xyz, r10.yzwy, r11.xyzx + iadd r14.xyz, -r9.yzwy, r14.xyzx + movc r6.yzw, r6.yyzw, r14.xxyz, r11.xxyz + movc r6.yzw, r0.wwww, r6.yyzw, r11.xxyz + and r11.xyz, r9.yzwy, r12.xyzx + and r14.xyz, r10.yzwy, r12.xyzx + iadd r14.xyz, -r9.yzwy, r14.xyzx + movc r11.xyz, r11.xyzx, r14.xyzx, r12.xyzx + movc r11.xyz, r0.wwww, r11.xyzx, r12.xyzx + and r12.xyz, r9.yzwy, r13.xyzx + and r10.yzw, r10.yyzw, r13.xxyz + iadd r9.xyz, -r9.yzwy, r10.yzwy + movc r9.xyz, r12.xyzx, r9.xyzx, r13.xyzx + movc r9.xyz, r0.wwww, r9.xyzx, r13.xyzx + iadd r10.yzw, r3.xxyz, r6.yyzw + movc r6.yzw, icb[r1.w + 0].zzzz, r10.yyzw, r6.yyzw + iadd r10.yzw, r3.xxyz, r11.xxyz + movc r10.yzw, icb[r1.w + 0].zzzz, r10.yyzw, r11.xxyz + iadd r11.xyz, r3.xyzx, r9.xyzx + movc r9.xyz, icb[r1.w + 0].zzzz, r11.xyzx, r9.xyzx + ult r11.xy, icb[r1.w + 32].xxxx, l(15, 16, 0, 0) + ishl r0.w, l(1), icb[r1.w + 32].x + iadd r0.w, r0.w, l(-1) + ieq r12.xyz, r0.wwww, r3.xyzx + ieq r13.xyz, r0.wwww, r6.yzwy + ishl r14.xyz, r3.xyzx, l(16) + ishl r15.xyz, r6.yzwy, l(16) + iadd r14.xyz, r14.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + iadd r15.xyz, r15.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + ushr r14.xyz, r14.xyzx, icb[r1.w + 32].x + ushr r15.xyz, r15.xyzx, icb[r1.w + 32].x + movc r12.xyz, r12.xyzx, l(0x0000ffff,0x0000ffff,0x0000ffff,0), r14.xyzx + movc r13.xyz, r13.xyzx, l(0x0000ffff,0x0000ffff,0x0000ffff,0), r15.xyzx + movc r12.xyz, r3.xyzx, r12.xyzx, l(0,0,0,0) + movc r13.xyz, r6.yzwy, r13.xyzx, l(0,0,0,0) + movc r12.xyz, r11.xxxx, r12.xyzx, r3.xyzx + movc r13.xyz, r11.xxxx, r13.xyzx, r6.yzwy + ige r14.xyz, r3.xyzx, l(0, 0, 0, 0) + ige r15.xyz, r6.yzwy, l(0, 0, 0, 0) + imax r16.xyz, -r3.xyzx, r3.xyzx + imax r17.xyz, -r6.yzwy, r6.yzwy + ige r18.xyz, r16.xyzx, r10.xxxx + ige r19.xyz, r17.xyzx, r10.xxxx + ishl r20.xyz, r16.xyzx, l(15) + ishl r21.xyz, r17.xyzx, l(15) + iadd r20.xyz, r20.xyzx, l(0x00004000, 0x00004000, 0x00004000, 0) + iadd r21.xyz, r21.xyzx, l(0x00004000, 0x00004000, 0x00004000, 0) + ushr r20.xyz, r20.xyzx, r6.x + ushr r21.xyz, r21.xyzx, r6.x + movc r18.xyz, r18.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r20.xyzx + movc r19.xyz, r19.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r21.xyzx + movc r16.xyz, r16.xyzx, r18.xyzx, l(0,0,0,0) + movc r17.xyz, r17.xyzx, r19.xyzx, l(0,0,0,0) + ineg r18.xyz, r16.xyzx + ineg r19.xyz, r17.xyzx + movc r14.xyz, r14.xyzx, r16.xyzx, r18.xyzx + movc r15.xyz, r15.xyzx, r17.xyzx, r19.xyzx + movc r3.xyz, r11.yyyy, r14.xyzx, r3.xyzx + movc r6.yzw, r11.yyyy, r15.xxyz, r6.yyzw + movc r3.xyz, r0.zzzz, r12.xyzx, r3.xyzx + movc r6.yzw, r0.zzzz, r13.xxyz, r6.yyzw + ieq r12.xyz, r0.wwww, r10.yzwy + ieq r13.xyz, r0.wwww, r9.xyzx + ishl r14.xyz, r10.yzwy, l(16) + ishl r15.xyz, r9.xyzx, l(16) + iadd r14.xyz, r14.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + iadd r15.xyz, r15.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + ushr r14.xyz, r14.xyzx, icb[r1.w + 32].x + ushr r15.xyz, r15.xyzx, icb[r1.w + 32].x + movc r12.xyz, r12.xyzx, l(0x0000ffff,0x0000ffff,0x0000ffff,0), r14.xyzx + movc r13.xyz, r13.xyzx, l(0x0000ffff,0x0000ffff,0x0000ffff,0), r15.xyzx + movc r12.xyz, r10.yzwy, r12.xyzx, l(0,0,0,0) + movc r13.xyz, r9.xyzx, r13.xyzx, l(0,0,0,0) + movc r12.xyz, r11.xxxx, r12.xyzx, r10.yzwy + movc r11.xzw, r11.xxxx, r13.xxyz, r9.xxyz + ige r13.xyz, r10.yzwy, l(0, 0, 0, 0) + ige r14.xyz, r9.xyzx, l(0, 0, 0, 0) + imax r15.xyz, -r10.yzwy, r10.yzwy + imax r16.xyz, -r9.xyzx, r9.xyzx + ige r17.xyz, r15.xyzx, r10.xxxx + ige r18.xyz, r16.xyzx, r10.xxxx + ishl r19.xyz, r15.xyzx, l(15) + ishl r20.xyz, r16.xyzx, l(15) + iadd r19.xyz, r19.xyzx, l(0x00004000, 0x00004000, 0x00004000, 0) + iadd r20.xyz, r20.xyzx, l(0x00004000, 0x00004000, 0x00004000, 0) + ushr r19.xyz, r19.xyzx, r6.x + ushr r20.xyz, r20.xyzx, r6.x + movc r17.xyz, r17.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r19.xyzx + movc r18.xyz, r18.xyzx, l(0x00007fff,0x00007fff,0x00007fff,0), r20.xyzx + movc r15.xyz, r15.xyzx, r17.xyzx, l(0,0,0,0) + movc r16.xyz, r16.xyzx, r18.xyzx, l(0,0,0,0) + ineg r17.xyz, r15.xyzx + ineg r18.xyz, r16.xyzx + movc r13.xyz, r13.xyzx, r15.xyzx, r17.xyzx + movc r14.xyz, r14.xyzx, r16.xyzx, r18.xyzx + movc r10.xyz, r11.yyyy, r13.xyzx, r10.yzwy + movc r9.xyz, r11.yyyy, r14.xyzx, r9.xyzx + movc r10.xyz, r0.zzzz, r12.xyzx, r10.xyzx + movc r9.xyz, r0.zzzz, r11.xzwx, r9.xyzx + ge r0.w, l(0.000000), r3.w + ge r1.w, l(0.000000), r2.y + mov r5.w, l(0) + mov r6.x, l(0) + loop + uge r7.w, r6.x, l(16) + breakc_nz r7.w + ushr r7.w, icb[r1.z + 0].x, r6.x + and r7.w, r7.w, l(1) + if_nz r7.w + iadd r7.w, r0.y, r6.x + ld_structured r11.xyz, r7.w, l(12), g0.xyzx + iadd r11.xyz, -r8.xyzx, r11.xyzx + itof r11.xyz, r11.xyzx + dp3 r7.w, r7.xyzx, r11.xyzx + ge r8.w, l(0.000000), r7.w + or r8.w, r0.w, r8.w + lt r9.w, r7.w, r3.w + mul r7.w, r7.w, l(63.499989) + div r7.w, r7.w, r3.w + ftou r7.w, r7.w + movc r7.w, r9.w, icb[r7.w + 46].x, l(7) + movc r7.w, r8.w, l(0), r7.w + iadd r8.w, l(64), -icb[r7.w + 0].w + imul null, r11.xyz, r9.xyzx, icb[r7.w + 0].wwww + imad r11.xyz, r10.xyzx, r8.wwww, r11.xyzx + iadd r11.xyz, r11.xyzx, l(32, 32, 32, 0) + ishr r11.xyz, r11.xyzx, l(6) + imul null, r12.xyz, r11.xyzx, l(31, 31, 31, 0) + ishr r13.xyz, r12.xyzx, l(6) + ilt r14.xyz, r11.xyzx, l(0, 0, 0, 0) + imul null, r11.xyz, r11.xyzx, l(-31, -31, -31, 0) + ishr r11.xyz, r11.xyzx, l(5) + ineg r11.xyz, r11.xyzx + ishr r12.xyz, r12.xyzx, l(5) + movc r11.xyz, r14.xyzx, r11.xyzx, r12.xyzx + ilt r12.xyz, r11.xyzx, l(0, 0, 0, 0) + ineg r14.xyz, r11.xyzx + or r14.xyz, r14.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + movc r11.xyz, r12.xyzx, r14.xyzx, r11.xyzx + movc r11.xyz, r0.zzzz, r13.xyzx, r11.xyzx + else + iadd r7.w, r0.y, r6.x + ld_structured r12.xyz, r7.w, l(12), g0.xyzx + iadd r12.xyz, -r5.xyzx, r12.xyzx + itof r12.xyz, r12.xyzx + dp3 r7.w, r4.xyzx, r12.xyzx + ge r8.w, l(0.000000), r7.w + or r8.w, r1.w, r8.w + lt r9.w, r7.w, r2.y + mul r7.w, r7.w, l(63.499989) + div r7.w, r7.w, r2.y + ftou r7.w, r7.w + movc r7.w, r9.w, icb[r7.w + 46].x, l(7) + movc r7.w, r8.w, l(0), r7.w + iadd r8.w, l(64), -icb[r7.w + 0].w + imul null, r12.xyz, r6.yzwy, icb[r7.w + 0].wwww + imad r12.xyz, r3.xyzx, r8.wwww, r12.xyzx + iadd r12.xyz, r12.xyzx, l(32, 32, 32, 0) + ishr r12.xyz, r12.xyzx, l(6) + imul null, r13.xyz, r12.xyzx, l(31, 31, 31, 0) + ishr r14.xyz, r13.xyzx, l(6) + ilt r15.xyz, r12.xyzx, l(0, 0, 0, 0) + imul null, r12.xyz, r12.xyzx, l(-31, -31, -31, 0) + ishr r12.xyz, r12.xyzx, l(5) + ineg r12.xyz, r12.xyzx + ishr r13.xyz, r13.xyzx, l(5) + movc r12.xyz, r15.xyzx, r12.xyzx, r13.xyzx + ilt r13.xyz, r12.xyzx, l(0, 0, 0, 0) + ineg r15.xyz, r12.xyzx + or r15.xyz, r15.xyzx, l(0x00008000, 0x00008000, 0x00008000, 0) + movc r12.xyz, r13.xyzx, r15.xyzx, r12.xyzx + movc r11.xyz, r0.zzzz, r14.xyzx, r12.xyzx + endif + and r12.xy, r11.xxxx, l(1023, 0x00007c00, 0, 0) + if_nz r12.y + ushr r7.w, r11.x, l(10) + and r7.w, r7.w, l(31) + else + if_nz r12.x + ishl r8.w, r12.x, l(1) + mov r9.w, r8.w + mov r7.w, l(0) + loop + and r10.w, r9.w, l(1024) + breakc_nz r10.w + iadd r7.w, r7.w, l(-1) + ishl r9.w, r9.w, l(1) + endloop + and r12.x, r9.w, l(1022) + else + mov r12.x, l(0) + mov r7.w, l(-112) + endif + endif + ishl r8.w, r11.x, l(16) + and r8.w, r8.w, l(0x80000000) + ishl r10.w, r7.w, l(23) + iadd r10.w, r10.w, l(0x38000000) + or r8.w, r8.w, r10.w + ishl r10.w, r12.x, l(13) + iadd r12.x, r8.w, r10.w + and r11.xw, r11.yyyy, l(1023, 0, 0, 0x00007c00) + if_nz r11.w + ushr r8.w, r11.y, l(10) + and r8.w, r8.w, l(31) + else + if_nz r11.x + ishl r10.w, r11.x, l(1) + mov r11.w, r10.w + mov r8.w, l(0) + loop + and r12.w, r11.w, l(1024) + breakc_nz r12.w + iadd r8.w, r8.w, l(-1) + ishl r11.w, r11.w, l(1) + endloop + and r11.x, r11.w, l(1022) + else + mov r11.x, l(0) + mov r8.w, l(-112) + endif + endif + ishl r10.w, r11.y, l(16) + and r10.w, r10.w, l(0x80000000) + ishl r11.y, r8.w, l(23) + iadd r11.y, r11.y, l(0x38000000) + or r10.w, r10.w, r11.y + ishl r11.x, r11.x, l(13) + iadd r12.y, r10.w, r11.x + and r11.xy, r11.zzzz, l(1023, 0x00007c00, 0, 0) + if_nz r11.y + ushr r10.w, r11.z, l(10) + and r10.w, r10.w, l(31) + else + if_nz r11.x + ishl r11.y, r11.x, l(1) + mov r12.w, r11.y + mov r10.w, l(0) + loop + and r13.x, r12.w, l(1024) + breakc_nz r13.x + iadd r10.w, r10.w, l(-1) + ishl r12.w, r12.w, l(1) + endloop + and r11.x, r12.w, l(1022) + else + mov r11.x, l(0) + mov r10.w, l(-112) + endif + endif + ishl r11.y, r11.z, l(16) + and r11.y, r11.y, l(0x80000000) + ishl r11.z, r10.w, l(23) + iadd r11.z, r11.z, l(0x38000000) + or r11.y, r11.z, r11.y + ishl r11.x, r11.x, l(13) + iadd r12.z, r11.x, r11.y + iadd r11.x, r0.y, r6.x + ld_structured r13.xyz, r11.x, l(24), g0.xyzx + add r11.xyz, r12.xyzx, -r13.xyzx + dp3 r11.x, r11.xyzx, r11.xyzx + add r5.w, r5.w, r11.x + iadd r6.x, r6.x, l(1) + endloop + movc r1.x, r4.w, l(100000002004087730000.000000), r5.w + iadd r1.y, cb0[0].w, l(1) + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(40), r1.xyzx +endif +sync_g_t +if_nz r2.x + ld_structured r3.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(16) + ld_structured r4.yzw, r0.y, l(40), g0.xxyz + lt r0.z, r4.y, r3.x + if_nz r0.z + ld_structured r4.x, r0.y, l(40), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(40), r4.xzwx + endif +endif +sync_g_t +if_nz r2.z + ld_structured r3.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(8) + ld_structured r4.yzw, r0.y, l(40), g0.xxyz + lt r0.z, r4.y, r3.x + if_nz r0.z + ld_structured r4.x, r0.y, l(40), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(40), r4.xzwx + endif +endif +sync_g_t +if_nz r2.w + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(4) + ld_structured r3.yzw, r0.y, l(40), g0.xxyz + lt r0.z, r3.y, r2.x + if_nz r0.z + ld_structured r3.x, r0.y, l(40), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(40), r3.xzwx + endif +endif +sync_g_t +ult r0.yz, r1.zzzz, l(0, 2, 1, 0) +if_nz r0.y + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(2) + ld_structured r2.yzw, r0.y, l(40), g0.xxyz + lt r0.w, r2.y, r1.x + if_nz r0.w + ld_structured r2.x, r0.y, l(40), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(40), r2.xzwx + endif +endif +sync_g_t +if_nz r0.z + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(1) + ld_structured r2.yzw, r0.y, l(40), g0.xxyz + lt r0.z, r2.y, r1.x + if_nz r0.z + ld_structured r2.x, r0.y, l(40), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(40), r2.xzwx + endif + ld_structured r1.x, r0.x, l(0), t1.xxxx + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(40), g0.xxxx + lt r0.y, r2.x, r1.x + if_nz r0.y + ld_structured r1.xyz, vThreadIDInGroupFlattened.x, l(40), g0.xyzx + mov r1.w, l(0) + else + ld_structured r1.xyzw, r0.x, l(0), t1.xyzw + endif + store_structured u0.xyzw, r0.x, l(0), r1.xyzw +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC6HEncode_TryModeLE10CS[] = +{ + 68, 88, 66, 67, 161, 2, + 137, 126, 42, 47, 246, 175, + 125, 91, 68, 30, 201, 32, + 221, 116, 1, 0, 0, 0, + 76, 96, 0, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 248, 95, 0, 0, + 64, 0, 5, 0, 254, 23, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 186, 1, + 0, 0, 204, 204, 0, 0, + 15, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 136, 136, 0, 0, 15, 0, + 0, 0, 255, 255, 255, 255, + 9, 0, 0, 0, 238, 238, + 0, 0, 15, 0, 0, 0, + 255, 255, 255, 255, 18, 0, + 0, 0, 200, 236, 0, 0, + 15, 0, 0, 0, 255, 255, + 255, 255, 27, 0, 0, 0, + 128, 200, 0, 0, 15, 0, + 0, 0, 255, 255, 255, 255, + 37, 0, 0, 0, 236, 254, + 0, 0, 15, 0, 0, 0, + 255, 255, 255, 255, 46, 0, + 0, 0, 200, 254, 0, 0, + 15, 0, 0, 0, 255, 255, + 255, 255, 55, 0, 0, 0, + 128, 236, 0, 0, 15, 0, + 0, 0, 255, 255, 255, 255, + 64, 0, 0, 0, 0, 200, + 0, 0, 15, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 236, 255, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 254, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 232, + 0, 0, 15, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 232, 255, 0, 0, + 15, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 255, 0, 0, 15, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 240, 255, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 240, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 247, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 113, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 206, 8, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 16, 115, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 49, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 140, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 8, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 49, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 102, 102, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 108, 54, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 23, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 15, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 142, 113, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 156, 57, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 5, 0, 0, 0, + 5, 0, 0, 0, 5, 0, + 0, 0, 7, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 0, 0, + 11, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 11, 0, + 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 11, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 0, 0, + 9, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 0, 0, 10, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, + 11, 0, 0, 0, 9, 0, + 0, 0, 9, 0, 0, 0, + 9, 0, 0, 0, 12, 0, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 4, 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, + 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 162, 0, 0, 4, 0, 112, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 0, 158, 0, + 0, 4, 0, 224, 17, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 95, 0, 0, 2, + 0, 64, 2, 0, 95, 0, + 0, 2, 18, 16, 2, 0, + 104, 0, 0, 2, 24, 0, + 0, 0, 105, 0, 0, 4, + 0, 0, 0, 0, 6, 0, + 0, 0, 4, 0, 0, 0, + 105, 0, 0, 4, 1, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 160, 0, + 0, 5, 0, 240, 17, 0, + 0, 0, 0, 0, 84, 0, + 0, 0, 64, 0, 0, 0, + 155, 0, 0, 4, 64, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 6, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 16, + 2, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 32, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 79, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 16, 0, 0, 0, + 32, 0, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 2, 0, 0, 0, + 78, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 0, 208, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 35, 0, 0, 11, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 6, 5, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 127, 255, 255, 127, 0, + 255, 255, 255, 127, 255, 255, + 127, 0, 79, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 239, 255, 71, + 255, 239, 255, 71, 6, 8, + 16, 0, 5, 0, 0, 0, + 79, 0, 0, 10, 50, 0, + 16, 0, 3, 0, 0, 0, + 134, 0, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 56, 0, 0, + 128, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 50, 0, 16, 0, + 6, 0, 0, 0, 134, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 11, + 50, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 128, + 65, 0, 0, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 113, 0, 0, 0, 113, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 162, 0, 16, 0, + 5, 0, 0, 0, 86, 13, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 128, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 85, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 5, 0, 0, 0, 134, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 200, 0, 0, 0, 200, + 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 9, + 50, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 7, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 10, + 50, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 255, 15, 0, 0, + 255, 15, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 10, 50, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 50, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 85, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 1, 0, + 0, 10, 50, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 12, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 14, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 6, 4, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 50, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 4, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 127, + 255, 255, 127, 0, 79, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 255, 239, 255, 71, + 42, 0, 16, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 56, + 85, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 30, 0, + 0, 8, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 113, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 200, + 55, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 15, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 255, 127, 0, 0, + 55, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 127, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 6, 5, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 255, 3, + 0, 0, 0, 124, 0, 0, + 255, 3, 0, 0, 0, 124, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 3, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 18, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 1, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 4, 0, 0, + 3, 0, 4, 3, 26, 0, + 16, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 41, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 1, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 254, 3, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 144, 255, 255, 255, + 21, 0, 0, 1, 21, 0, + 0, 1, 41, 0, 0, 7, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 18, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 1, + 1, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 4, 0, 0, 3, 0, + 4, 3, 10, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 1, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 254, 3, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 66, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 144, 255, 255, 255, 21, 0, + 0, 1, 21, 0, 0, 1, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 56, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 10, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 3, + 0, 0, 0, 124, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 18, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 1, + 1, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 4, 0, 0, 3, 0, + 4, 3, 26, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 254, 3, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 255, + 255, 255, 21, 0, 0, 1, + 21, 0, 0, 1, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 10, 130, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 208, 179, 89, 62, 89, 23, + 55, 63, 152, 221, 147, 61, + 0, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 32, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 95, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 78, 0, 0, 11, 114, 0, + 16, 0, 3, 0, 0, 0, + 0, 208, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 31, 0, 0, 0, 0, 0, + 0, 0, 79, 0, 0, 10, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 255, 123, 0, 0, 255, 123, + 0, 0, 255, 123, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 78, 0, 0, 11, + 114, 0, 16, 0, 7, 0, + 0, 0, 0, 208, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 224, 255, + 15, 0, 224, 255, 15, 0, + 224, 255, 15, 0, 0, 0, + 0, 0, 78, 0, 0, 11, + 114, 0, 16, 0, 5, 0, + 0, 0, 0, 208, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 1, 128, 255, 255, 1, 128, + 255, 255, 1, 128, 255, 255, + 0, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 3, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 54, 0, + 0, 6, 18, 48, 32, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 127, 127, 54, 0, + 0, 6, 34, 48, 32, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 127, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 127, 127, 54, 0, + 0, 6, 34, 48, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 127, 255, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 58, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 85, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 144, 144, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 48, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 49, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 48, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 49, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 48, 32, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 48, + 32, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 54, 0, 0, 6, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 40, 0, 0, 5, + 50, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 40, 0, + 0, 5, 66, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 43, 0, + 0, 5, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 49, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 29, 0, 0, 7, 34, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 28, 0, + 0, 5, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 55, 0, 0, 10, + 114, 0, 16, 0, 4, 0, + 0, 0, 246, 15, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 246, 15, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 66, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 6, 0, 0, 0, + 246, 15, 16, 0, 3, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 3, 0, 0, 0, + 55, 0, 0, 9, 66, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 40, 0, 0, 5, 50, 0, + 16, 0, 7, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 40, 0, 0, 5, + 66, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 26, 144, + 144, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 49, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 29, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 28, 0, + 0, 5, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 55, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 246, 15, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 8, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 66, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 9, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 3, 0, 0, 0, + 55, 0, 0, 9, 66, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 32, 0, 0, 11, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 138, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 95, 0, 0, 0, 96, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 144, 208, 0, + 32, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 10, 0, 0, 0, + 6, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 11, 0, 0, 0, 6, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 9, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 10, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 41, 0, 0, 9, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 10, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 86, 5, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 86, 5, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 55, 0, + 0, 15, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 15, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 12, 0, 0, 0, 6, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 13, 0, + 0, 0, 6, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 41, 0, 0, 9, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 10, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 41, 0, 0, 9, + 114, 0, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 10, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 86, 5, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 86, 5, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 6, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 10, 144, 208, 0, + 32, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 246, 15, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 33, 0, 0, 10, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 17, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 10, 144, 208, 0, + 32, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 246, 15, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 246, 15, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 22, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 2, 64, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 21, 0, 0, 0, + 246, 15, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 22, 0, 0, 0, + 246, 15, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 55, 0, + 0, 15, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 15, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 13, 0, + 0, 0, 246, 15, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 33, 0, 0, 10, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 32, 0, 0, 10, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 10, 114, 0, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 2, 64, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 255, 127, 0, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 18, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 246, 15, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 21, 0, 0, 0, + 246, 15, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 21, 0, + 0, 1, 30, 0, 0, 8, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 10, 114, 0, 16, 0, + 6, 0, 0, 0, 166, 154, + 144, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 55, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 166, 154, + 144, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 10, 114, 0, 16, 0, + 3, 0, 0, 0, 166, 154, + 144, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 31, 0, 4, 4, + 42, 144, 144, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 33, 0, 0, 10, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 12, 114, 0, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 0, 0, 0, 0, + 150, 151, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 13, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 13, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 13, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 33, 0, + 0, 7, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 34, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 15, 0, 0, 0, 10, 0, + 16, 0, 15, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 41, 0, + 0, 9, 18, 0, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 9, 34, 0, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 26, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 9, 66, 0, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 42, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 9, 130, 0, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 58, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 15, 0, 0, 0, 70, 14, + 16, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 1, 0, 0, 7, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 6, 0, + 16, 0, 15, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 0, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 1, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 150, 7, 16, 0, 15, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 33, 0, 0, 7, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 34, 0, 0, 7, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 22, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 34, 0, 0, 7, + 114, 0, 16, 0, 22, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 22, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 23, 0, 0, 0, + 70, 2, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 22, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 23, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 19, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 150, 7, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 18, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 7, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 150, 7, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 22, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 18, 0, + 0, 1, 41, 0, 0, 9, + 130, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 10, 144, + 208, 0, 32, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 7, 114, 0, + 16, 0, 16, 0, 0, 0, + 246, 15, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 1, 0, + 0, 7, 114, 0, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 246, 15, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 1, 0, 0, 7, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 246, 15, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 30, 0, + 0, 12, 242, 0, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 70, 158, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 6, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 1, 0, + 0, 7, 226, 0, 16, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 10, 0, 0, 0, + 6, 9, 16, 0, 16, 0, + 0, 0, 30, 0, 0, 8, + 226, 0, 16, 0, 6, 0, + 0, 0, 6, 0, 16, 128, + 65, 0, 0, 0, 9, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 150, 7, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 60, 0, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 144, 144, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 226, 0, + 16, 0, 6, 0, 0, 0, + 86, 14, 16, 0, 9, 0, + 0, 0, 6, 9, 16, 0, + 11, 0, 0, 0, 1, 0, + 0, 7, 114, 0, 16, 0, + 14, 0, 0, 0, 150, 7, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 30, 0, 0, 8, + 114, 0, 16, 0, 14, 0, + 0, 0, 150, 7, 16, 128, + 65, 0, 0, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 86, 14, + 16, 0, 6, 0, 0, 0, + 6, 9, 16, 0, 14, 0, + 0, 0, 6, 9, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 6, 9, 16, 0, + 11, 0, 0, 0, 1, 0, + 0, 7, 114, 0, 16, 0, + 11, 0, 0, 0, 150, 7, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 14, 0, + 0, 0, 150, 7, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 30, 0, 0, 8, 114, 0, + 16, 0, 14, 0, 0, 0, + 150, 7, 16, 128, 65, 0, + 0, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 11, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 150, 7, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 226, 0, + 16, 0, 10, 0, 0, 0, + 86, 14, 16, 0, 10, 0, + 0, 0, 6, 9, 16, 0, + 13, 0, 0, 0, 30, 0, + 0, 8, 114, 0, 16, 0, + 9, 0, 0, 0, 150, 7, + 16, 128, 65, 0, 0, 0, + 9, 0, 0, 0, 150, 7, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 9, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 30, 0, 0, 7, 226, 0, + 16, 0, 10, 0, 0, 0, + 6, 9, 16, 0, 3, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 10, 226, 0, 16, 0, + 6, 0, 0, 0, 166, 154, + 144, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 86, 14, + 16, 0, 10, 0, 0, 0, + 86, 14, 16, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 226, 0, 16, 0, 10, 0, + 0, 0, 6, 9, 16, 0, + 3, 0, 0, 0, 6, 9, + 16, 0, 11, 0, 0, 0, + 55, 0, 0, 10, 226, 0, + 16, 0, 10, 0, 0, 0, + 166, 154, 144, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 86, 14, 16, 0, 10, 0, + 0, 0, 6, 9, 16, 0, + 11, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 55, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 166, 154, 144, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 79, 0, 0, 12, 50, 0, + 16, 0, 11, 0, 0, 0, + 6, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 15, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 41, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 10, 144, 208, 0, + 32, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 32, 0, + 0, 7, 114, 0, 16, 0, + 12, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 32, 0, 0, 7, + 114, 0, 16, 0, 13, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 15, 0, 0, 0, 150, 7, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 2, 64, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 10, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 85, 0, + 0, 9, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 10, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 13, 0, 0, 0, 150, 7, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 12, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 150, 7, 16, 0, + 6, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 15, 0, + 0, 0, 150, 7, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 36, 0, 0, 8, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 36, 0, 0, 8, + 114, 0, 16, 0, 17, 0, + 0, 0, 150, 7, 16, 128, + 65, 0, 0, 0, 6, 0, + 0, 0, 150, 7, 16, 0, + 6, 0, 0, 0, 33, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 6, 0, 16, 0, 10, 0, + 0, 0, 33, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 6, 0, + 16, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 17, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 21, 0, 0, 0, + 70, 2, 16, 0, 21, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 21, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 21, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 86, 5, + 16, 0, 11, 0, 0, 0, + 6, 9, 16, 0, 15, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 6, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 6, 9, 16, 0, 13, 0, + 0, 0, 86, 14, 16, 0, + 6, 0, 0, 0, 32, 0, + 0, 7, 114, 0, 16, 0, + 12, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 10, 0, + 0, 0, 32, 0, 0, 7, + 114, 0, 16, 0, 13, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 14, 0, 0, 0, + 150, 7, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 2, 64, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 10, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 85, 0, + 0, 9, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 10, 144, 208, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 0, 0, 255, 255, 0, 0, + 255, 255, 0, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 12, 0, 0, 0, 150, 7, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 12, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 150, 7, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 210, 0, 16, 0, + 11, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 6, 9, 16, 0, 13, 0, + 0, 0, 6, 9, 16, 0, + 9, 0, 0, 0, 33, 0, + 0, 10, 114, 0, 16, 0, + 13, 0, 0, 0, 150, 7, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 10, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 36, 0, 0, 8, 114, 0, + 16, 0, 15, 0, 0, 0, + 150, 7, 16, 128, 65, 0, + 0, 0, 10, 0, 0, 0, + 150, 7, 16, 0, 10, 0, + 0, 0, 36, 0, 0, 8, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 33, 0, + 0, 7, 114, 0, 16, 0, + 17, 0, 0, 0, 70, 2, + 16, 0, 15, 0, 0, 0, + 6, 0, 16, 0, 10, 0, + 0, 0, 33, 0, 0, 7, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 6, 0, + 16, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 1, 64, 0, 0, 15, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 2, 64, + 0, 0, 0, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 20, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 2, 64, 0, 0, + 255, 127, 0, 0, 255, 127, + 0, 0, 255, 127, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 12, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 86, 5, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 150, 7, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 86, 5, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 9, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 134, 3, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 29, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 29, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 80, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 3, 0, 4, 3, 58, 0, + 16, 0, 7, 0, 0, 0, + 85, 0, 0, 8, 130, 0, + 16, 0, 7, 0, 0, 0, + 10, 144, 144, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 8, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 43, 0, 0, 5, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 29, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 49, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 14, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 28, 0, 0, 5, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 55, 0, + 0, 11, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 144, 208, 0, 46, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 9, 130, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 58, 144, 144, 128, + 65, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 38, 0, 0, 9, 0, 208, + 0, 0, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 246, 159, 144, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 35, 0, 0, 9, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 246, 15, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 34, 0, 0, 10, + 114, 0, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 38, 0, 0, 11, 0, 208, + 0, 0, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 225, 255, + 255, 255, 225, 255, 255, 255, + 225, 255, 255, 255, 0, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 42, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 34, 0, 0, 10, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 0, + 0, 5, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 60, 0, 0, 10, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 2, 64, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 128, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 14, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 18, 0, + 0, 1, 30, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 29, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 49, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 28, 0, + 0, 5, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 55, 0, 0, 11, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 10, 144, 208, 0, + 46, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 9, + 130, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 58, 144, + 144, 128, 65, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 38, 0, 0, 9, + 0, 208, 0, 0, 114, 0, + 16, 0, 12, 0, 0, 0, + 150, 7, 16, 0, 6, 0, + 0, 0, 246, 159, 144, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 35, 0, 0, 9, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 32, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 38, 0, + 0, 11, 0, 208, 0, 0, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 31, 0, 0, 0, + 31, 0, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 0, + 42, 0, 0, 7, 114, 0, + 16, 0, 14, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 34, 0, + 0, 10, 114, 0, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 225, 255, 255, 255, 225, 255, + 255, 255, 225, 255, 255, 255, + 0, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 42, 0, + 0, 7, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 34, 0, 0, 10, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 40, 0, 0, 5, 114, 0, + 16, 0, 15, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 60, 0, 0, 10, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 11, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 21, 0, 0, 1, 1, 0, + 0, 10, 50, 0, 16, 0, + 12, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 255, 3, + 0, 0, 0, 124, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 12, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 18, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 12, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 1, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 0, 4, 0, 0, + 3, 0, 4, 3, 58, 0, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 41, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 1, 0, 0, 7, 18, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 254, 3, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 18, 0, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 144, 255, 255, 255, + 21, 0, 0, 1, 21, 0, + 0, 1, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 128, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 56, + 60, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 1, 0, 0, 10, 146, 0, + 16, 0, 11, 0, 0, 0, + 86, 5, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 255, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 124, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 11, 0, 0, 0, 85, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 10, 0, 16, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 1, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 0, 4, + 0, 0, 3, 0, 4, 3, + 58, 0, 16, 0, 12, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 41, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 1, 0, 0, 7, + 18, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 254, 3, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 18, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 144, 255, + 255, 255, 21, 0, 0, 1, + 21, 0, 0, 1, 41, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 128, + 41, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 56, 60, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 1, 0, 0, 10, + 50, 0, 16, 0, 11, 0, + 0, 0, 166, 10, 16, 0, + 11, 0, 0, 0, 2, 64, + 0, 0, 255, 3, 0, 0, + 0, 124, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 11, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 18, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 12, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 1, + 1, 0, 0, 7, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 0, 4, 0, 0, 3, 0, + 4, 3, 10, 0, 16, 0, + 13, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 255, 255, + 255, 255, 41, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 1, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 254, 3, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 18, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 144, 255, 255, 255, 21, 0, + 0, 1, 21, 0, 0, 1, + 41, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 128, 41, 0, 0, 7, + 66, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 56, 60, 0, + 0, 7, 34, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 13, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 13, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 55, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 236, 120, 173, 96, + 58, 0, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 21, 0, 0, 1, 190, 24, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 167, 0, + 0, 9, 226, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 249, 17, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 114, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 134, 3, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 226, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 249, + 17, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 114, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 134, 3, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 190, 24, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 134, 3, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 190, 24, + 0, 1, 79, 0, 0, 10, + 98, 0, 16, 0, 0, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 40, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 134, 3, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 190, 24, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 226, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 249, 17, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 40, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 114, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 134, 3, 16, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 167, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 6, 112, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 49, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 40, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 167, 0, + 0, 9, 242, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 168, 0, 0, 9, + 242, 224, 17, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 62, 0, 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeLE10CS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeLE10CS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..fb50085063d186ddd3fe0201439861d7579b4c1f Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC6HEncode_TryModeLE10CS.pdb differ diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_EncodeBlockCS.inc b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_EncodeBlockCS.inc new file mode 100644 index 0000000000000000000000000000000000000000..bbd2d6af0ac5686f8d8863a4501a5ff15abdf017 --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_EncodeBlockCS.inc @@ -0,0 +1,10151 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { 0x0000cccc, -0.000000, 15, 0}, + { 0x00008888, 65981199646559862000000000.000000, 15, 0}, + { 0x0000eeee, 15358528172589056.000000, 15, 0}, + { 0x0000ecc8, 3584194248704.000000, 15, 0}, + { 0x0000c880, -0.000000, 15, 0}, + { 0x0000feec, -0.000000, 15, 0}, + { 0x0000fec8, 14680365989888.000000, 15, 0}, + { 0x0000ec80, 15362462362632192.000000, 15, 0}, + { 0x0000c800, -0.000000, 15, 0}, + { 0x0000ffec, -0.000000, 15, 0}, + { 0x0000fe80, -0.000000, 15, 0}, + { 0x0000e800, -0.000000, 15, 0}, + { 0x0000ffe8, -0.000000, 15, 0}, + { 0x0000ff00, -0.000000, 15, 0}, + { 0x0000fff0, -0.000000, 15, 0}, + { 0x0000f000, 0.000000, 15, 0}, + { 0x0000f710, -0.000000, 15, 0}, + { 142, 0.000000, 2, 0}, + { 0x00007100, -0.000000, 8, 0}, + { 2254, 22076467445760.000000, 2, 0}, + { 140, -0.000000, 2, 0}, + { 0x00007310, 70798013459086900000000000.000000, 8, 0}, + { 0x00003100, -0.000000, 8, 0}, + { 0x00008cce, 0.000000, 15, 0}, + { 2188, 0x0050a4a4, 2, 0}, + { 0x00003110, -0.000000, 8, 0}, + { 0x00006666, 0.000000, 2, 0}, + { 0x0000366c, 17610885206241624000000000.000000, 2, 0}, + { 6120, -0.000000, 8, 0}, + { 4080, -0.000000, 8, 0}, + { 0x0000718e, 22097854464.000000, 2, 0}, + { 0x0000399c, 65888818352238725000000000.000000, 2, 0}, + { 0x0000aaaa, -0.000000, 15, 0}, + { 0x0000f0f0, 19411582976.000000, 15, 0}, + { 0x00005a5a, -0.000000, 6, 0}, + { 0x000033cc, 0.000000, 8, 0}, + { 0x00003c3c, 0.000000, 2, 0}, + { 0x000055aa, 0.000000, 8, 0}, + { 0x00009696, 0.000000, 15, 0}, + { 0x0000a55a, 22151331840.000000, 15, 0}, + { 0x000073ce, 9304358912.000000, 2, 0}, + { 5064, -0.000000, 8, 0}, + { 0x0000324c, 271536072765004600000000.000000, 2, 0}, + { 0x00003bdc, -0.000000, 2, 0}, + { 0x00006996, 21517107200.000000, 2, 0}, + { 0x0000c33c, 12724757752857623000000000.000000, 15, 0}, + { 0x00009966, 1365.320801, 15, 0}, + { 1632, 272006464738884190000000.000000, 6, 0}, + { 626, -0.000000, 6, 0}, + { 1252, 5783798415360.000000, 2, 0}, + { 0x00004e40, -0.000000, 6, 0}, + { 0x00002720, -0.000000, 8, 0}, + { 0x0000c936, -0.000000, 15, 0}, + { 0x0000936c, -0.000000, 15, 0}, + { 0x000039c6, -0.000000, 2, 0}, + { 0x0000639c, -0.000000, 2, 0}, + { 0x00009336, -0.000000, 15, 0}, + { 0x00009cc6, -0.000000, 15, 0}, + { 0x0000817e, -0.000000, 15, 0}, + { 0x0000e718, -0.000000, 15, 0}, + { 0x0000ccf0, 4.007874, 15, 0}, + { 4044, -0.000000, 2, 0}, + { 0x00007744, -0.000000, 2, 0}, + { 0x0000ee22, 0.000000, 15, 0}, + { 0, 0, 3, 15}, + { 0, 0, 3, 8}, + { 0, 0, 15, 8}, + { 1, 0, 15, 3}, + { 1, 0, 8, 15}, + { 1, 0, 3, 15}, + { 1, 0, 15, 3}, + { 2, 0, 15, 8}, + { 2, 0, 8, 15}, + { 2, 0, 8, 15}, + { 2, 0, 6, 15}, + { 2, 0, 6, 15}, + { 3, 0, 6, 15}, + { 3, 0, 5, 15}, + { 3, 0, 3, 15}, + { 3, 0, 3, 8}, + { 4, 0, 3, 15}, + { 4, 0, 3, 8}, + { 4, 0, 8, 15}, + { 4, 0, 15, 3}, + { 5, 0, 3, 15}, + { 5, 0, 3, 8}, + { 5, 0, 6, 15}, + { 5, 0, 10, 8}, + { 6, 0, 5, 3}, + { 6, 0, 8, 15}, + { 6, 0, 8, 6}, + { 6, 0, 6, 10}, + { 6, 0, 8, 15}, + { 7, 0, 5, 15}, + { 7, 0, 15, 10}, + { 7, 0, 15, 8}, + { 7, 0, 8, 15}, + { 8, 0, 15, 3}, + { 8, 0, 3, 15}, + { 8, 0, 5, 10}, + { 8, 0, 6, 10}, + { 9, 0, 10, 8}, + { 9, 0, 8, 9}, + { 9, 0, 15, 10}, + { 9, 0, 15, 6}, + { 10, 0, 3, 15}, + { 10, 0, 15, 8}, + { 10, 0, 5, 15}, + { 10, 0, 15, 3}, + { 10, 0, 15, 6}, + { 11, 0, 15, 6}, + { 11, 0, 15, 8}, + { 11, 0, 3, 15}, + { 11, 0, 15, 3}, + { 12, 0, 5, 15}, + { 12, 0, 5, 15}, + { 12, 0, 5, 15}, + { 12, 0, 8, 15}, + { 13, 0, 5, 15}, + { 13, 0, 10, 15}, + { 13, 0, 5, 15}, + { 13, 0, 10, 15}, + { 14, 0, 8, 15}, + { 14, 0, 13, 15}, + { 14, 0, 15, 3}, + { 14, 0, 12, 15}, + { 15, 0, 3, 15}, + { 15, 0, 3, 8}, + { 0, 15, 0, 0}, + { 0, 15, 0, 0}, + { 0, 15, 0, 0}, + { 0, 15, 0, 0}, + { 0, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 1, 15, 0, 0}, + { 2, 15, 0, 0}, + { 2, 15, 0, 0}, + { 2, 15, 0, 0}, + { 2, 2, 0, 0}, + { 2, 8, 0, 0}, + { 2, 2, 0, 0}, + { 2, 2, 0, 0}, + { 2, 8, 0, 0}, + { 2, 8, 0, 0}, + { 3, 15, 0, 0}, + { 3, 2, 0, 0}, + { 3, 8, 0, 0}, + { 3, 2, 0, 0}, + { 3, 2, 0, 0}, + { 3, 8, 0, 0}, + { 3, 8, 0, 0}, + { 3, 2, 0, 0}, + { 3, 2, 0, 0}, + { 3, 15, 0, 0}, + { 4, 15, 0, 0}, + { 4, 6, 0, 0}, + { 4, 8, 0, 0}, + { 4, 2, 0, 0}, + { 4, 8, 0, 0}, + { 4, 15, 0, 0}, + { 4, 15, 0, 0}, + { 4, 2, 0, 0}, + { 4, 8, 0, 0}, + { 5, 2, 0, 0}, + { 5, 2, 0, 0}, + { 5, 2, 0, 0}, + { 5, 15, 0, 0}, + { 5, 15, 0, 0}, + { 5, 6, 0, 0}, + { 5, 6, 0, 0}, + { 5, 2, 0, 0}, + { 5, 6, 0, 0}, + { 6, 8, 0, 0}, + { 6, 15, 0, 0}, + { 6, 15, 0, 0}, + { 6, 2, 0, 0}, + { 6, 2, 0, 0}, + { 6, 15, 0, 0}, + { 6, 15, 0, 0}, + { 6, 15, 0, 0}, + { 6, 15, 0, 0}, + { 7, 15, 0, 0}, + { 7, 2, 0, 0}, + { 7, 2, 0, 0}, + { 7, 15, 0, 0}, + { 0, 3, 15, 0}, + { 0, 3, 8, 0}, + { 0, 8, 15, 0}, + { 0, 3, 15, 0}, + { 0, 8, 15, 0}, + { 0, 3, 15, 0}, + { 0, 3, 15, 0}, + { 0, 8, 15, 0}, + { 0, 8, 15, 0}, + { 0, 8, 15, 0}, + { 0, 6, 15, 0}, + { 1, 6, 15, 0}, + { 1, 6, 15, 0}, + { 1, 5, 15, 0}, + { 1, 3, 15, 0}, + { 1, 3, 8, 0}, + { 1, 3, 15, 0}, + { 1, 3, 8, 0}, + { 1, 8, 15, 0}, + { 1, 3, 15, 0}, + { 1, 3, 15, 0}, + { 1, 3, 8, 0}, + { 1, 6, 15, 0}, + { 1, 8, 10, 0}, + { 1, 3, 5, 0}, + { 1, 8, 15, 0}, + { 1, 6, 8, 0}, + { 1, 6, 10, 0}, + { 1, 8, 15, 0}, + { 1, 5, 15, 0}, + { 1, 10, 15, 0}, + { 1, 8, 15, 0}, + { 1, 8, 15, 0}, + { 2, 3, 15, 0}, + { 2, 3, 15, 0}, + { 2, 5, 10, 0}, + { 2, 6, 10, 0}, + { 2, 8, 10, 0}, + { 2, 8, 9, 0}, + { 2, 10, 15, 0}, + { 2, 6, 15, 0}, + { 2, 3, 15, 0}, + { 2, 8, 15, 0}, + { 2, 5, 15, 0}, + { 2, 3, 15, 0}, + { 2, 6, 15, 0}, + { 2, 6, 15, 0}, + { 2, 8, 15, 0}, + { 2, 3, 15, 0}, + { 2, 3, 15, 0}, + { 2, 5, 15, 0}, + { 2, 5, 15, 0}, + { 2, 5, 15, 0}, + { 2, 8, 15, 0}, + { 3, 5, 15, 0}, + { 3, 10, 15, 0}, + { 3, 5, 15, 0}, + { 3, 10, 15, 0}, + { 3, 8, 15, 0}, + { 3, 13, 15, 0}, + { 3, 3, 15, 0}, + { 3, 12, 15, 0}, + { 3, 3, 15, 0}, + { 3, 3, 8, 0} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_structured t1, 16 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 15 +dcl_tgsm_structured g0, 100, 64 +dcl_thread_group 64, 1, 1 +ushr r0.x, vThreadIDInGroupFlattened.x, l(4) +ishl r0.y, vThreadGroupID.x, l(2) +iadd r0.y, r0.y, cb0[1].x +iadd r0.x, r0.x, r0.y +uge r0.y, r0.x, cb0[1].y +if_nz r0.y + ret +endif +and r0.y, vThreadIDInGroupFlattened.x, l(48) +iadd r0.z, -r0.y, vThreadIDInGroupFlattened.x +ld_structured r1.xyz, r0.x, l(4), t1.xyzx +and r0.w, r1.x, l(0x7fffffff) +ld_structured r2.x, r0.x, l(4), t1.xxxx +ushr r1.x, r2.x, l(31) +ult r2.xyzw, r0.zzzz, l(16, 8, 4, 2) +if_nz r2.x + udiv r1.w, null, r0.x, cb0[0].y + imad r3.x, -r1.w, cb0[0].y, r0.x + ishl r3.x, r3.x, l(2) + ishl r1.w, r1.w, l(2) + and r3.y, r0.z, l(3) + iadd r3.x, r3.y, r3.x + ushr r4.x, r0.z, l(2) + iadd r3.y, r1.w, r4.x + mov r3.zw, l(0,0,0,0) + ld r3.xyzw, r3.xyzw, t0.xyzw + mul r3.xyzw, r3.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000) + ftou r3.xyzw, r3.xyzw + umin r3.xyzw, r3.xyzw, l(255, 255, 255, 255) + ieq r4.xy, r0.wwww, l(4, 5, 0, 0) + or r1.w, r4.y, r4.x + ieq r4.xyz, r1.zzzz, l(1, 2, 3, 0) + movc r5.zw, r4.zzzz, r3.wwwz, r3.zzzw + mov r5.xy, r3.xyxx + movc r5.yzw, r4.yyyy, r3.wwzy, r5.yyzw + movc r4.xyzw, r4.xxxx, r3.wyzx, r5.xyzw + movc r3.xyzw, r1.wwww, r4.xyzw, r3.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(0), r3.xyzw +endif +iadd r1.w, r1.y, l(-64) +if_nz r2.x + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(0), g0.xyzw + ishl r4.x, r0.z, l(1) + ushr r4.x, icb[r1.w + 0].y, r4.x + and r4.x, r4.x, l(3) + ieq r4.yz, r0.wwww, l(0, 0, 2, 0) + or r4.y, r4.z, r4.y + ieq r4.x, r4.x, l(2) + movc r5.xyzw, r4.xxxx, r3.xyzw, l(-1,-1,-1,-1) + and r3.xyzw, r3.xyzw, r4.xxxx + movc r5.xyzw, r4.yyyy, r5.xyzw, l(-1,-1,-1,-1) + and r3.xyzw, r3.xyzw, r4.yyyy + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r3.xyzw +endif +if_nz r2.y + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r4.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r5.x, vThreadIDInGroupFlattened.x, l(8) + ld_structured r6.xyzw, r5.x, l(36), g0.xyzw + ld_structured r5.xyzw, r5.x, l(52), g0.xyzw + umin r3.xyzw, r3.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r3.xyzw + umax r3.xyzw, r4.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r3.xyzw +endif +if_nz r2.z + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r4.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r5.x, vThreadIDInGroupFlattened.x, l(4) + ld_structured r6.xyzw, r5.x, l(36), g0.xyzw + ld_structured r5.xyzw, r5.x, l(52), g0.xyzw + umin r3.xyzw, r3.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r3.xyzw + umax r3.xyzw, r4.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r3.xyzw +endif +if_nz r2.w + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r4.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r5.x, vThreadIDInGroupFlattened.x, l(2) + ld_structured r6.xyzw, r5.x, l(36), g0.xyzw + ld_structured r5.xyzw, r5.x, l(52), g0.xyzw + umin r3.xyzw, r3.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r3.xyzw + umax r3.xyzw, r4.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r3.xyzw +endif +ult r3.xy, r0.zzzz, l(1, 3, 0, 0) +if_nz r3.x + ld_structured r4.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r5.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r3.z, vThreadIDInGroupFlattened.x, l(1) + ld_structured r6.xyzw, r3.z, l(36), g0.xyzw + ld_structured r7.xyzw, r3.z, l(52), g0.xyzw + umin r4.xyzw, r4.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r4.xyzw + umax r4.xyzw, r5.xyzw, r7.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r4.xyzw +endif +ieq r3.zw, r0.zzzz, l(0, 0, 2, 1) +if_nz r3.z + ld_structured r4.xyzw, r0.y, l(36), g0.xyzw + ld_structured r5.xyzw, r0.y, l(52), g0.xyzw +endif +if_nz r2.x + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(0), g0.xyzw + ushr r3.z, icb[r1.y + 0].x, r0.z + and r3.z, r3.z, l(1) + ishl r7.x, r0.z, l(1) + ushr r7.x, icb[r1.w + 0].y, r7.x + and r7.x, r7.x, l(3) + ieq r8.xyzw, r0.wwww, l(0, 2, 1, 3) + ieq r7.x, r7.x, l(1) + movc r9.xyzw, r7.xxxx, r6.xyzw, l(-1,-1,-1,-1) + and r7.xyzw, r6.xyzw, r7.xxxx + or r8.xy, r8.ywyy, r8.xzxx + ieq r8.z, r0.w, l(7) + or r8.y, r8.z, r8.y + ieq r3.z, r3.z, l(1) + movc r10.xyzw, r3.zzzz, r6.xyzw, l(-1,-1,-1,-1) + and r6.xyzw, r6.xyzw, r3.zzzz + movc r10.xyzw, r8.yyyy, r10.xyzw, l(-1,-1,-1,-1) + and r6.xyzw, r6.xyzw, r8.yyyy + movc r9.xyzw, r8.xxxx, r9.xyzw, r10.xyzw + movc r6.xyzw, r8.xxxx, r7.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r2.y + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r3.z, vThreadIDInGroupFlattened.x, l(8) + ld_structured r8.xyzw, r3.z, l(36), g0.xyzw + ld_structured r9.xyzw, r3.z, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r2.z + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r3.z, vThreadIDInGroupFlattened.x, l(4) + ld_structured r8.xyzw, r3.z, l(36), g0.xyzw + ld_structured r9.xyzw, r3.z, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r2.w + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r3.z, vThreadIDInGroupFlattened.x, l(2) + ld_structured r8.xyzw, r3.z, l(36), g0.xyzw + ld_structured r9.xyzw, r3.z, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r3.x + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r3.z, vThreadIDInGroupFlattened.x, l(1) + ld_structured r8.xyzw, r3.z, l(36), g0.xyzw + ld_structured r9.xyzw, r3.z, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r3.w + ld_structured r4.xyzw, r0.y, l(36), g0.xyzw + ld_structured r5.xyzw, r0.y, l(52), g0.xyzw +endif +if_nz r2.x + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(0), g0.xyzw + ushr r3.z, icb[r1.y + 0].x, r0.z + and r3.z, r3.z, l(1) + ishl r7.x, r0.z, l(1) + ushr r7.x, icb[r1.w + 0].y, r7.x + and r7.x, r7.x, l(3) + ieq r8.xyzw, r0.wwww, l(0, 2, 1, 3) + movc r9.xyzw, r7.xxxx, l(-1,-1,-1,-1), r6.xyzw + movc r7.xyzw, r7.xxxx, l(0,0,0,0), r6.xyzw + or r8.xy, r8.ywyy, r8.xzxx + ieq r10.xyzw, r0.wwww, l(7, 4, 5, 6) + or r8.y, r8.y, r10.x + movc r11.xyzw, r3.zzzz, l(-1,-1,-1,-1), r6.xyzw + movc r12.xyzw, r3.zzzz, l(0,0,0,0), r6.xyzw + or r3.z, r10.z, r10.y + or r3.z, r10.w, r3.z + movc r10.xyzw, r3.zzzz, r6.xyzw, l(-1,-1,-1,-1) + and r6.xyzw, r6.xyzw, r3.zzzz + movc r10.xyzw, r8.yyyy, r11.xyzw, r10.xyzw + movc r6.xyzw, r8.yyyy, r12.xyzw, r6.xyzw + movc r9.xyzw, r8.xxxx, r9.xyzw, r10.xyzw + movc r6.xyzw, r8.xxxx, r7.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r2.y + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r2.y, vThreadIDInGroupFlattened.x, l(8) + ld_structured r8.xyzw, r2.y, l(36), g0.xyzw + ld_structured r9.xyzw, r2.y, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r2.z + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r2.y, vThreadIDInGroupFlattened.x, l(4) + ld_structured r8.xyzw, r2.y, l(36), g0.xyzw + ld_structured r9.xyzw, r2.y, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r2.w + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r2.y, vThreadIDInGroupFlattened.x, l(2) + ld_structured r8.xyzw, r2.y, l(36), g0.xyzw + ld_structured r9.xyzw, r2.y, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_nz r3.x + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r7.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r2.y, vThreadIDInGroupFlattened.x, l(1) + ld_structured r8.xyzw, r2.y, l(36), g0.xyzw + ld_structured r9.xyzw, r2.y, l(52), g0.xyzw + umin r6.xyzw, r6.xyzw, r8.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r6.xyzw + umax r6.xyzw, r7.xyzw, r9.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r6.xyzw +endif +if_z r0.z + ld_structured r4.xyzw, r0.y, l(36), g0.xyzw + ld_structured r5.xyzw, r0.y, l(52), g0.xyzw +endif +if_nz r3.y + ieq r2.yzw, r0.wwww, l(0, 1, 4, 5) + ushr r3.x, r1.z, r0.z + and r3.x, r3.x, l(1) + ishl r3.y, r0.z, l(1) + ushr r6.x, r1.z, r3.y + iadd r3.y, r3.y, l(1) + ushr r6.y, r1.z, r3.y + and r3.yz, r6.xxyx, l(0, 1, 1, 0) + movc r3.xy, r2.yyyy, r3.xxxx, r3.yzyy + if_z r0.w + iadd r6.xyz, r4.xyzx, l(4, 4, 4, 0) + umin r6.xyz, r6.xyzx, l(255, 255, 255, 0) + ushr r6.xyz, r6.xyzx, l(3) + and r6.xyz, r6.xyzx, l(30, 30, 30, 0) + iadd r6.xyz, r3.xxxx, r6.xyzx + ishl r6.xyz, r6.xyzx, l(3) + ushr r7.xyz, r6.xyzx, l(5) + iadd r7.xyz, r6.xyzx, r7.xyzx + iadd r8.xyz, r5.xyzx, l(4, 4, 4, 0) + umin r8.xyz, r8.xyzx, l(255, 255, 255, 0) + ushr r8.xyz, r8.xyzx, l(3) + and r8.xyz, r8.xyzx, l(30, 30, 30, 0) + iadd r8.xyz, r3.yyyy, r8.xyzx + ishl r8.xyz, r8.xyzx, l(3) + ushr r9.xyz, r8.xyzx, l(5) + iadd r5.xyz, r8.xyzx, r9.xyzx + mov r5.w, l(255) + mov r4.xyw, l(255,2040,0,2040) + else + if_nz r2.y + iadd r9.xyz, r4.xyzx, l(1, 1, 1, 0) + umin r9.xyz, r9.xyzx, l(255, 255, 255, 0) + ushr r9.xyz, r9.xyzx, l(1) + and r9.xyz, r9.xyzx, l(126, 126, 126, 0) + iadd r9.xyz, r3.xxxx, r9.xyzx + ishl r6.xyz, r9.xyzx, l(1) + ushr r9.xyz, r6.xyzx, l(7) + iadd r7.xyz, r6.xyzx, r9.xyzx + iadd r9.xyz, r5.xyzx, l(1, 1, 1, 0) + umin r9.xyz, r9.xyzx, l(255, 255, 255, 0) + ushr r9.xyz, r9.xyzx, l(1) + and r9.xyz, r9.xyzx, l(126, 126, 126, 0) + iadd r9.xyz, r3.yyyy, r9.xyzx + ishl r8.xyz, r9.xyzx, l(1) + ushr r9.xyz, r8.xyzx, l(7) + iadd r5.xyz, r8.xyzx, r9.xyzx + mov r5.w, l(255) + mov r4.xyw, l(255,510,0,510) + else + ieq r2.y, r0.w, l(2) + if_nz r2.y + iadd r9.xyz, r4.xyzx, l(4, 4, 4, 0) + umin r9.xyz, r9.xyzx, l(255, 255, 255, 0) + and r6.xyz, r9.xyzx, l(248, 248, 248, 0) + ushr r9.xyz, r9.xyzx, l(5) + iadd r7.xyz, r6.xyzx, r9.xyzx + iadd r9.xyz, r5.xyzx, l(4, 4, 4, 0) + umin r9.xyz, r9.xyzx, l(255, 255, 255, 0) + and r8.xyz, r9.xyzx, l(248, 248, 248, 0) + ushr r9.xyz, r9.xyzx, l(5) + iadd r5.xyz, r8.xyzx, r9.xyzx + mov r5.w, l(255) + mov r4.xyw, l(255,2040,0,2040) + else + ieq r2.y, r0.w, l(3) + if_nz r2.y + and r9.xyz, r4.xyzx, l(-2, -2, -2, 0) + iadd r6.xyz, r3.xxxx, r9.xyzx + and r9.xyz, r5.xyzx, l(-2, -2, -2, 0) + iadd r8.xyz, r3.yyyy, r9.xyzx + mov r7.xyz, r6.xyzx + mov r5.xyz, r8.xyzx + mov r5.w, l(255) + mov r4.xyw, l(255,255,0,255) + else + ieq r2.y, r0.w, l(4) + if_nz r2.y + iadd r9.xyzw, r4.xyzw, l(4, 4, 4, 2) + umin r9.xyzw, r9.xyzw, l(255, 255, 255, 255) + and r6.xyzw, r9.xyzw, l(248, 248, 248, 252) + ushr r10.xyz, r9.xyzx, l(5) + ushr r10.w, r9.w, l(6) + iadd r7.xyzw, r6.xyzw, r10.xyzw + iadd r9.xyzw, r5.xyzw, l(4, 4, 4, 2) + umin r9.xyzw, r9.xyzw, l(255, 255, 255, 255) + and r4.xyzw, r9.xwzy, l(248, 252, 248, 248) + ushr r10.xyz, r9.xyzx, l(5) + ushr r10.w, r9.w, l(6) + iadd r5.xyzw, r4.xwzy, r10.xyzw + mov r8.xyz, r4.xwzx + mov r4.x, r7.w + mov r4.w, r6.w + else + ieq r2.y, r0.w, l(5) + if_nz r2.y + iadd r9.xyz, r4.xyzx, l(1, 1, 1, 0) + umin r9.xyz, r9.xyzx, l(255, 255, 255, 0) + and r6.xyz, r9.xyzx, l(254, 254, 254, 0) + ushr r9.xyz, r9.xyzx, l(7) + iadd r7.xyz, r6.xyzx, r9.xyzx + iadd r9.xyz, r5.xyzx, l(1, 1, 1, 0) + umin r9.xyz, r9.xyzx, l(255, 255, 255, 0) + and r8.xyz, r9.xyzx, l(254, 254, 254, 0) + ushr r9.xyz, r9.xyzx, l(7) + iadd r5.xyz, r8.xyzx, r9.xyzx + mov r4.x, r4.w + mov r4.y, r5.w + else + ieq r2.y, r0.w, l(6) + if_nz r2.y + and r9.xyzw, r4.xyzw, l(-2, -2, -2, -2) + iadd r6.xyzw, r3.xxxx, r9.xyzw + and r9.xyzw, r5.xyzw, l(-2, -2, -2, -2) + iadd r4.xyzw, r3.yyyy, r9.xwzy + mov r7.xyz, r6.xyzx + mov r5.xyzw, r4.xwzy + mov r8.xyz, r4.xwzx + mov r4.xw, r6.wwww + else + iadd r9.xyzw, r4.xyzw, l(2, 2, 2, 2) + umin r9.xyzw, r9.xyzw, l(255, 255, 255, 255) + ushr r9.xyzw, r9.xyzw, l(2) + and r9.xyzw, r9.xyzw, l(62, 62, 62, 62) + iadd r9.xyzw, r3.xxxx, r9.xyzw + ishl r6.xyzw, r9.xyzw, l(2) + ushr r10.xyzw, r6.xyzw, l(6) + iadd r4.xyzw, r6.wxzy, r10.wxzy + iadd r10.xyzw, r5.xyzw, l(2, 2, 2, 2) + umin r10.xyzw, r10.xyzw, l(255, 255, 255, 255) + ushr r10.xyzw, r10.xyzw, l(2) + and r10.xyzw, r10.xyzw, l(62, 62, 62, 62) + iadd r10.xyzw, r3.yyyy, r10.xwyz + ishl r8.xyzw, r10.xzwy, l(2) + ushr r11.xyzw, r8.xyzw, l(6) + iadd r5.xyzw, r8.xyzw, r11.xyzw + mov r10.x, r9.w + ishl r3.xy, r10.xyxx, l(2) + mov r7.xyz, r4.ywzy + mov r4.yw, r3.yyyx + endif + endif + endif + endif + endif + endif + endif + ineg r9.xyz, r7.xyzx + ineg r9.w, r4.x + iadd r10.xyzw, r5.xyzw, r9.xyzw + ult r2.y, r0.w, l(4) + movc r2.y, r2.y, l(0), r10.w + or r2.z, r2.w, r2.z + if_nz r2.z + if_z r0.z + imul null, r2.zw, r10.xxxy, r10.xxxy + iadd r2.z, r2.w, r2.z + imad r2.z, r10.z, r10.z, r2.z + imul null, r2.w, r2.y, r2.y + ld_structured r11.xyzw, r0.y, l(0), g0.xyzw + iadd r3.xyz, -r7.xyzx, r11.xyzx + imul null, r3.xy, r3.xyxx, r10.xyxx + iadd r3.x, r3.y, r3.x + imad r3.x, r10.z, r3.z, r3.x + iadd r3.y, -r4.x, r11.w + imul null, r3.y, r2.y, r3.y + ilt r3.z, l(0), r2.z + ilt r10.w, l(0), r3.x + and r3.z, r3.z, r10.w + itof r3.x, r3.x + mul r3.x, r3.x, l(63.499989) + ftou r3.x, r3.x + ishl r2.z, r2.z, l(5) + ult r2.z, r2.z, r3.x + and r2.z, r2.z, r3.z + movc r11.xyz, r2.zzzz, r5.xyzx, r7.xyzx + movc r5.xyz, r2.zzzz, r7.xyzx, r5.xyzx + movc r12.xyz, r2.zzzz, r8.xyzx, r6.xyzx + movc r8.xyz, r2.zzzz, r6.xyzx, r8.xyzx + ilt r2.z, l(0), r2.w + ilt r3.x, l(0), r3.y + and r2.z, r2.z, r3.x + itof r3.x, r3.y + mul r3.x, r3.x, l(63.499989) + ftou r3.x, r3.x + ishl r2.w, r2.w, l(5) + ult r2.w, r2.w, r3.x + and r2.z, r2.w, r2.z + mov r4.z, r5.w + movc r13.xyzw, r2.zzzz, r4.zxyw, r4.xzwy + mov r11.w, r13.x + mov r5.w, r13.y + mov r12.w, r13.z + mov r6.xyzw, r12.xyzw + mov r8.w, r13.w + else + mov r7.w, r4.x + mov r11.xyzw, r7.xyzw + mov r6.w, r4.w + mov r8.w, r4.y + endif + else + if_z r0.z + mov r2.z, l(0) + else + if_nz r3.w + mov r2.z, icb[r1.y + 0].z + else + mov r2.z, icb[r1.y + 0].w + endif + endif + imul null, r3.xy, r10.xyxx, r10.xyxx + iadd r2.w, r3.y, r3.x + imad r2.w, r10.z, r10.z, r2.w + imad r2.w, r2.y, r2.y, r2.w + iadd r2.z, r0.y, r2.z + ld_structured r3.xyzw, r2.z, l(0), g0.xyzw + iadd r3.xyzw, r9.xyzw, r3.xyzw + imul null, r3.xy, r3.xyxx, r10.xyxx + iadd r2.z, r3.y, r3.x + imad r2.z, r10.z, r3.z, r2.z + imad r2.y, r2.y, r3.w, r2.z + ilt r2.z, l(0), r2.w + ilt r3.x, l(0), r2.y + and r2.z, r2.z, r3.x + itof r2.y, r2.y + mul r2.y, r2.y, l(63.499989) + ftou r2.y, r2.y + ishl r2.w, r2.w, l(5) + ult r2.y, r2.w, r2.y + and r2.y, r2.y, r2.z + mov r7.w, r4.x + movc r11.xyzw, r2.yyyy, r5.xyzw, r7.xyzw + movc r5.xyzw, r2.yyyy, r7.xyzw, r5.xyzw + mov r8.w, r4.y + mov r4.xyz, r6.xyzx + movc r6.xyzw, r2.yyyy, r8.xyzw, r4.xyzw + movc r8.xyzw, r2.yyyy, r4.xyzw, r8.xyzw + endif + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r11.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(68), r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(84), r8.xyzw +endif +if_nz r2.x + ieq r2.xyzw, r0.wwww, l(0, 1, 6, 4) + or r3.x, r2.y, r2.x + movc r3.yz, r1.xxxx, l(0,1,2,0), l(0,2,1,0) + movc r3.yz, r2.wwww, r3.yyzy, l(0,2,2,0) + movc r3.yz, r2.zzzz, l(0,0,0,0), r3.yyzy + movc r3.xy, r3.xxxx, l(1,1,0,0), r3.yzyy + ieq r4.xyzw, r0.wwww, l(2, 3, 7, 5) + ishl r2.z, r0.z, l(1) + ushr r1.w, icb[r1.w + 0].y, r2.z + and r1.w, r1.w, l(3) + or r2.xyz, r2.xywx, r4.xywx + or r2.y, r4.z, r2.y + ushr r2.w, icb[r1.y + 0].x, r0.z + and r2.y, r2.y, r2.w + and r2.y, r2.y, l(1) + movc r1.w, r2.x, r1.w, r2.y + iadd r1.w, r0.y, r1.w + ld_structured r4.xyzw, r1.w, l(36), g0.xyzw + ld_structured r5.xyzw, r1.w, l(52), g0.xyzw + iadd r5.xyzw, -r4.xyzw, r5.xyzw + ult r1.w, r0.w, l(4) + movc r1.w, r1.w, l(0), r5.w + if_nz r2.z + imul null, r2.xy, r5.xyxx, r5.xyxx + iadd r2.x, r2.y, r2.x + imad r2.x, r5.z, r5.z, r2.x + imul null, r2.y, r1.w, r1.w + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(0), g0.xyzw + iadd r7.xyzw, -r4.xyzw, r6.xyzw + imul null, r2.zw, r5.xxxy, r7.xxxy + iadd r2.z, r2.w, r2.z + imad r2.z, r5.z, r7.z, r2.z + ige r2.w, l(0), r2.x + ige r3.z, l(0), r2.z + or r2.w, r2.w, r3.z + ilt r3.z, r2.z, r2.x + itof r2.xz, r2.xxzx + mul r2.z, r2.z, l(63.499989) + div r2.x, r2.z, r2.x + ftou r2.x, r2.x + ishl r3.yw, r3.xxxy, l(6) + iadd r2.x, r2.x, r3.y + iadd r6.xy, r3.ywyy, l(11, 11, 0, 0) + udiv null, r6.xy, r6.xyxx, l(68, 68, 0, 0) + ult r7.xy, r3.ywyy, l(1, 1, 0, 0) + movc r6.xy, r7.xyxx, l(15,15,0,0), r6.xyxx + movc r2.x, r3.z, icb[r2.x + 64].x, r6.x + movc r7.y, r2.w, l(0), r2.x + imul null, r2.x, r1.w, r7.w + ige r2.zw, l(0, 0, 0, 0), r2.yyyx + or r2.z, r2.w, r2.z + ilt r2.w, r2.x, r2.y + itof r2.xy, r2.xyxx + mul r2.x, r2.x, l(63.499989) + div r2.x, r2.x, r2.y + ftou r2.x, r2.x + iadd r2.x, r2.x, r3.w + movc r2.x, r2.w, icb[r2.x + 64].x, r6.y + movc r7.x, r2.z, l(0), r2.x + movc r2.xy, r1.xxxx, r7.xyxx, r7.yxyy + else + imul null, r2.zw, r5.xxxy, r5.xxxy + iadd r2.z, r2.w, r2.z + imad r2.z, r5.z, r5.z, r2.z + imad r2.z, r1.w, r1.w, r2.z + ld_structured r6.xyzw, vThreadIDInGroupFlattened.x, l(0), g0.xyzw + iadd r4.xyzw, -r4.xyzw, r6.xyzw + imul null, r3.yz, r4.xxyx, r5.xxyx + iadd r2.w, r3.z, r3.y + imad r2.w, r5.z, r4.z, r2.w + imad r1.w, r1.w, r4.w, r2.w + ige r2.w, l(0), r2.z + ige r3.y, l(0), r1.w + or r2.w, r2.w, r3.y + ilt r3.y, r1.w, r2.z + itof r1.w, r1.w + mul r1.w, r1.w, l(63.499989) + itof r2.z, r2.z + div r1.w, r1.w, r2.z + ftou r1.w, r1.w + ishl r2.z, r3.x, l(6) + iadd r1.w, r1.w, r2.z + iadd r3.x, r2.z, l(11) + udiv null, r3.x, r3.x, l(68) + ult r2.z, r2.z, l(1) + movc r2.z, r2.z, l(15), r3.x + movc r1.w, r3.y, icb[r1.w + 64].x, r2.z + movc r2.x, r2.w, l(0), r1.w + mov r2.y, l(0) + endif + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(16), r2.xyxx +endif +if_z r0.z + if_z r0.w + ishl r0.z, r1.y, l(1) + iadd r0.z, r0.z, l(-128) + iadd r0.z, r0.z, l(1) + ld_structured r2.xyz, r0.y, l(68), g0.xyzx + ishl r3.x, r2.x, l(1) + ishl r3.y, r2.y, l(25) + ishl r3.z, r2.z, l(17) + and r3.xyz, r3.xyzx, l(480, 0xe0000000, 0x01e00000, 0) + or r0.z, r0.z, r3.x + ld_structured r4.xyz, r0.y, l(84), g0.xyzx + ishl r5.x, r4.x, l(5) + ishl r5.y, r4.z, l(21) + and r2.xw, r5.xxxy, l(7680, 0, 0, 0x1e000000) + or r0.z, r0.z, r2.x + iadd r3.xw, r0.yyyy, l(1, 0, 0, 2) + ld_structured r5.xyz, r3.x, l(68), g0.xyzx + ishl r6.x, r5.x, l(9) + ishl r6.y, r5.y, l(1) + ishl r6.z, r5.z, l(25) + and r6.xyz, r6.xyzx, l(0x0001e000, 480, 0xe0000000, 0) + or r0.z, r0.z, r6.x + ld_structured r7.xyz, r3.x, l(84), g0.xyzx + ishl r8.x, r7.x, l(13) + ishl r8.y, r7.y, l(5) + and r4.xw, r8.xxxy, l(0x001e0000, 0, 0, 7680) + or r0.z, r0.z, r4.x + ld_structured r8.xyz, r3.w, l(68), g0.xyzx + ishl r9.x, r8.x, l(17) + ishl r9.y, r8.y, l(9) + ishl r9.z, r8.z, l(1) + and r9.xyz, r9.xyzx, l(0x01e00000, 0x0001e000, 480, 0) + or r0.z, r0.z, r9.x + ld_structured r10.xyz, r3.w, l(84), g0.xyzx + ishl r11.x, r10.x, l(21) + ishl r11.y, r10.y, l(13) + ishl r11.z, r10.z, l(5) + and r11.xyz, r11.xyzx, l(0x1e000000, 0x001e0000, 7680, 0) + or r0.z, r0.z, r11.x + or r12.x, r3.y, r0.z + ld_structured r13.xy, r0.y, l(68), g0.xyxx + ushr r0.z, r13.y, l(7) + and r0.z, r0.z, l(1) + ushr r1.w, r4.y, l(3) + and r1.w, r1.w, l(30) + iadd r0.z, r0.z, r1.w + iadd r0.z, r6.y, r0.z + iadd r0.z, r4.w, r0.z + iadd r0.z, r9.y, r0.z + iadd r0.z, r11.y, r0.z + iadd r0.z, r3.z, r0.z + iadd r0.z, r2.w, r0.z + iadd r12.y, r6.z, r0.z + ld_structured r2.x, r3.x, l(76), g0.xxxx + ushr r0.z, r2.x, l(7) + and r0.z, r0.z, l(1) + ushr r1.w, r7.z, l(3) + and r1.w, r1.w, l(30) + iadd r0.z, r0.z, r1.w + iadd r0.z, r9.z, r0.z + iadd r0.z, r11.z, r0.z + ishl r1.w, r13.x, l(10) + and r1.w, r1.w, l(8192) + iadd r0.z, r0.z, r1.w + ld_structured r2.x, r0.y, l(84), g0.xxxx + ishl r1.w, r2.x, l(11) + and r1.w, r1.w, l(0x00004000) + iadd r0.z, r0.z, r1.w + ld_structured r2.x, r3.x, l(68), g0.xxxx + ishl r1.w, r2.x, l(12) + and r1.w, r1.w, l(0x00008000) + iadd r0.z, r0.z, r1.w + ld_structured r2.x, r3.x, l(84), g0.xxxx + ishl r1.w, r2.x, l(13) + and r1.w, r1.w, l(0x00010000) + iadd r0.z, r0.z, r1.w + ld_structured r2.x, r3.w, l(68), g0.xxxx + ishl r1.w, r2.x, l(14) + and r1.w, r1.w, l(0x00020000) + iadd r0.z, r0.z, r1.w + ld_structured r2.x, r3.w, l(84), g0.xxxx + ishl r1.w, r2.x, l(15) + and r1.w, r1.w, l(0x00040000) + iadd r0.z, r0.z, r1.w + ld_structured r2.x, r0.y, l(16), g0.xxxx + ishl r1.w, r2.x, l(19) + iadd r0.z, r0.z, r1.w + umin r1.w, l(4), icb[r1.y + 128].y + mov r12.z, r0.z + mov r2.x, l(1) + loop + ult r2.y, r1.w, r2.x + breakc_nz r2.y + iadd r2.y, r0.y, r2.x + ld_structured r3.x, r2.y, l(16), g0.xxxx + imad r2.y, r2.x, l(3), l(18) + ishl r2.y, r3.x, r2.y + or r12.z, r2.y, r12.z + iadd r2.x, r2.x, l(1) + endloop + ult r0.z, icb[r1.y + 128].y, l(4) + if_nz r0.z + iadd r0.z, r0.y, l(4) + ld_structured r3.x, r0.z, l(16), g0.xxxx + ishl r0.z, r3.x, l(29) + or r12.z, r0.z, r12.z + iadd r2.z, r2.x, l(1) + mov r2.y, l(0) + else + iadd r0.z, r0.y, l(4) + ld_structured r3.x, r0.z, l(16), g0.xxxx + ushr r0.z, r3.x, l(2) + and r0.z, r0.z, l(1) + mov r2.y, r0.z + mov r2.z, r2.x + loop + ult r1.w, icb[r1.y + 128].y, r2.z + breakc_nz r1.w + iadd r1.w, r0.y, r2.z + ld_structured r3.x, r1.w, l(16), g0.xxxx + imad r1.w, r2.z, l(3), l(-14) + ishl r1.w, r3.x, r1.w + or r2.y, r1.w, r2.y + iadd r2.z, r2.z, l(1) + endloop + endif + mov r0.z, r2.y + mov r1.w, r2.z + loop + ult r2.x, icb[r1.y + 128].z, r1.w + breakc_nz r2.x + iadd r2.x, r0.y, r1.w + ld_structured r3.x, r2.x, l(16), g0.xxxx + imad r2.x, r1.w, l(3), l(-15) + ishl r2.x, r3.x, r2.x + or r0.z, r0.z, r2.x + iadd r1.w, r1.w, l(1) + endloop + mov r12.w, r0.z + mov r2.x, r1.w + loop + uge r2.y, r2.x, l(16) + breakc_nz r2.y + iadd r2.y, r0.y, r2.x + ld_structured r3.x, r2.y, l(16), g0.xxxx + imad r2.y, r2.x, l(3), l(-16) + ishl r2.y, r3.x, r2.y + or r12.w, r2.y, r12.w + iadd r2.x, r2.x, l(1) + endloop + else + ieq r0.z, r0.w, l(1) + if_nz r0.z + ishl r0.z, r1.y, l(2) + iadd r0.z, r0.z, l(2) + ld_structured r2.xyz, r0.y, l(68), g0.xyzx + ishl r3.x, r2.x, l(6) + ishl r3.y, r2.z, l(22) + and r2.xz, r3.xxyx, l(0x00003f00, 0, 0x3f000000, 0) + or r0.z, r0.z, r2.x + ld_structured r3.xyz, r0.y, l(84), g0.xyzx + ishl r4.x, r3.x, l(12) + ishl r4.y, r3.y, l(4) + ishl r4.z, r3.z, l(28) + and r3.xyz, r4.xyzx, l(0x000fc000, 4032, 0xc0000000, 0) + or r0.z, r0.z, r3.x + iadd r1.w, r0.y, l(1) + ld_structured r4.xyz, r1.w, l(68), g0.xyzx + ishl r5.x, r4.x, l(18) + ishl r5.y, r4.y, l(10) + ishl r5.z, r4.z, l(2) + and r4.xyz, r5.xyzx, l(0x03f00000, 0x0003f000, 1008, 0) + or r0.z, r0.z, r4.x + ld_structured r5.xyz, r1.w, l(84), g0.xyzx + ishl r6.x, r5.x, l(24) + ishl r6.y, r5.y, l(16) + ishl r6.z, r5.z, l(8) + and r5.xyz, r6.xyzx, l(0xfc000000, 0x00fc0000, 0x0000fc00, 0) + or r12.x, r0.z, r5.x + ushr r0.z, r2.y, l(2) + and r0.z, r0.z, l(63) + iadd r0.z, r3.y, r0.z + iadd r0.z, r4.y, r0.z + iadd r0.z, r5.y, r0.z + iadd r0.z, r2.z, r0.z + iadd r12.y, r3.z, r0.z + ld_structured r2.x, r0.y, l(92), g0.xxxx + ushr r0.z, r2.x, l(4) + and r0.z, r0.z, l(15) + iadd r0.z, r4.z, r0.z + iadd r0.z, r5.z, r0.z + ld_structured r2.x, r0.y, l(68), g0.xxxx + ishl r2.x, r2.x, l(15) + and r2.x, r2.x, l(0x00010000) + iadd r0.z, r0.z, r2.x + ld_structured r2.x, r1.w, l(68), g0.xxxx + ishl r2.x, r2.x, l(16) + and r2.x, r2.x, l(0x00020000) + iadd r0.z, r0.z, r2.x + ld_structured r2.x, r0.y, l(16), g0.xxxx + ishl r2.x, r2.x, l(18) + iadd r0.z, r0.z, r2.x + ieq r2.y, l(15), icb[r1.y + 128].y + if_nz r2.y + iadd r3.xyzw, r0.yyyy, l(15, 14, 13, 12) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.y, r4.x, l(30) + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(27) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(24) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(21) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(11, 10, 9, 8) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(18) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(15) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(12) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(9) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(7, 6, 5, 4) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(6) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(3) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + or r12.w, r2.y, r4.x + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.y, r3.x, l(29) + iadd r2.zw, r0.yyyy, l(0, 0, 3, 2) + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r3.x, l(26) + or r2.y, r2.z, r2.y + ld_structured r3.x, r2.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r1.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(20) + or r2.y, r2.z, r2.y + or r2.y, r2.x, r2.y + or r12.z, r0.z, r2.y + else + ieq r2.y, l(2), icb[r1.y + 128].y + if_nz r2.y + iadd r3.xyzw, r0.yyyy, l(15, 14, 13, 12) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.y, r4.x, l(29) + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(26) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(20) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(11, 10, 9, 8) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(17) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(14) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(11) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(8) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(7, 6, 5, 4) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(5) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(2) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ushr r2.z, r4.x, l(1) + or r12.w, r2.z, r2.y + ishl r2.y, r4.x, l(31) + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(28) + or r2.y, r2.z, r2.y + iadd r2.zw, r0.yyyy, l(0, 0, 3, 2) + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r3.x, l(25) + or r2.y, r2.z, r2.y + ld_structured r3.x, r2.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r1.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(20) + or r2.y, r2.z, r2.y + or r2.y, r2.x, r2.y + or r12.z, r0.z, r2.y + else + ieq r2.y, l(8), icb[r1.y + 128].y + if_nz r2.y + iadd r3.xyzw, r0.yyyy, l(15, 14, 13, 12) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.y, r4.x, l(29) + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(26) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(20) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(11, 10, 9, 8) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(17) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(14) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(11) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(9) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(7, 6, 5, 4) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(6) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(3) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + or r12.w, r2.y, r4.x + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.y, r3.x, l(29) + iadd r2.zw, r0.yyyy, l(0, 0, 3, 2) + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r3.x, l(26) + or r2.y, r2.z, r2.y + ld_structured r3.x, r2.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r1.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(20) + or r2.y, r2.z, r2.y + or r2.y, r2.x, r2.y + or r12.z, r0.z, r2.y + else + iadd r3.xyzw, r0.yyyy, l(15, 14, 13, 12) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.y, r4.x, l(29) + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(26) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(20) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(11, 10, 9, 8) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(17) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(14) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + ishl r2.z, r4.x, l(11) + or r2.y, r2.z, r2.y + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(8) + or r2.y, r2.z, r2.y + iadd r3.xyzw, r0.yyyy, l(7, 6, 5, 4) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r2.z, r4.x, l(6) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.y, l(16), g0.xxxx + ishl r2.z, r4.x, l(4) + or r2.y, r2.z, r2.y + ld_structured r4.x, r3.z, l(16), g0.xxxx + or r12.w, r2.y, r4.x + ld_structured r3.x, r3.w, l(16), g0.xxxx + ishl r2.y, r3.x, l(29) + iadd r2.zw, r0.yyyy, l(0, 0, 3, 2) + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r3.x, l(26) + or r2.y, r2.z, r2.y + ld_structured r3.x, r2.w, l(16), g0.xxxx + ishl r2.z, r3.x, l(23) + or r2.y, r2.z, r2.y + ld_structured r3.x, r1.w, l(16), g0.xxxx + ishl r1.w, r3.x, l(20) + or r1.w, r1.w, r2.y + or r1.w, r2.x, r1.w + or r12.z, r0.z, r1.w + endif + endif + endif + else + ieq r0.z, r0.w, l(2) + if_nz r0.z + ishl r0.z, r1.y, l(3) + iadd r0.z, r0.z, l(-512) + iadd r0.z, r0.z, l(4) + ld_structured r2.xyz, r0.y, l(68), g0.xyzx + ishl r3.x, r2.x, l(6) + ishl r3.y, r2.y, l(4) + ishl r3.z, r2.z, l(2) + and r3.xyz, r3.xyzx, l(0x00003e00, 3968, 992, 0) + or r0.z, r0.z, r3.x + ld_structured r4.xyz, r0.y, l(84), g0.xyzx + ishl r5.x, r4.x, l(11) + ishl r5.y, r4.y, l(9) + ishl r5.z, r4.z, l(7) + and r5.xyz, r5.xyzx, l(0x0007c000, 0x0001f000, 0x00007c00, 0) + or r0.z, r0.z, r5.x + iadd r2.xw, r0.yyyy, l(1, 0, 0, 2) + ld_structured r6.xyz, r2.x, l(68), g0.xyzx + ishl r7.x, r6.x, l(16) + ishl r7.y, r6.y, l(14) + ishl r7.z, r6.z, l(12) + and r7.xyz, r7.xyzx, l(0x00f80000, 0x003e0000, 0x000f8000, 0) + or r0.z, r0.z, r7.x + ld_structured r8.xyz, r2.x, l(84), g0.xyzx + ishl r9.x, r8.x, l(21) + ishl r9.y, r8.y, l(19) + ishl r9.z, r8.z, l(17) + and r9.xyz, r9.xyzx, l(0x1f000000, 0x07c00000, 0x01f00000, 0) + or r0.z, r0.z, r9.x + ld_structured r10.xyz, r2.w, l(68), g0.xyzx + ishl r11.x, r10.x, l(26) + ishl r11.y, r10.y, l(24) + ishl r11.z, r10.z, l(22) + and r11.xyz, r11.xyzx, l(0xe0000000, 0xf8000000, 0x3e000000, 0) + or r12.x, r0.z, r11.x + ld_structured r13.x, r2.w, l(68), g0.xxxx + ushr r0.z, r13.x, l(6) + and r0.z, r0.z, l(3) + ld_structured r13.xyz, r2.w, l(84), g0.xyzx + ushr r14.x, r13.x, l(1) + ushr r14.y, r13.y, l(3) + and r3.xw, r14.xxxy, l(124, 0, 0, 31) + iadd r0.z, r0.z, r3.x + iadd r0.z, r3.y, r0.z + iadd r0.z, r5.y, r0.z + iadd r0.z, r7.y, r0.z + iadd r0.z, r9.y, r0.z + iadd r12.y, r11.y, r0.z + iadd r0.z, r3.z, r3.w + iadd r0.z, r5.z, r0.z + iadd r0.z, r7.z, r0.z + iadd r0.z, r9.z, r0.z + iadd r0.z, r11.z, r0.z + ishl r1.w, r13.z, l(27) + and r1.w, r1.w, l(0xc0000000) + iadd r12.z, r0.z, r1.w + ld_structured r2.x, r2.w, l(92), g0.xxxx + ushr r0.z, r2.x, l(5) + and r0.z, r0.z, l(7) + ld_structured r2.x, r0.y, l(16), g0.xxxx + ishl r1.w, r2.x, l(3) + iadd r0.z, r0.z, r1.w + mov r1.w, r0.z + mov r2.x, l(1) + loop + ult r2.y, icb[r1.y + 128].y, r2.x + breakc_nz r2.y + iadd r2.y, r0.y, r2.x + ld_structured r3.x, r2.y, l(16), g0.xxxx + ishl r2.y, r2.x, l(1) + iadd r2.y, r2.y, l(2) + ishl r2.y, r3.x, r2.y + or r1.w, r1.w, r2.y + iadd r2.x, r2.x, l(1) + endloop + mov r0.z, r1.w + mov r2.y, r2.x + loop + ult r2.z, icb[r1.y + 128].z, r2.y + breakc_nz r2.z + iadd r2.z, r0.y, r2.y + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r2.y, l(1) + iadd r2.z, r2.z, l(1) + ishl r2.z, r3.x, r2.z + or r0.z, r0.z, r2.z + iadd r2.y, r2.y, l(1) + endloop + mov r12.w, r0.z + mov r1.w, r2.y + loop + uge r2.x, r1.w, l(16) + breakc_nz r2.x + iadd r2.x, r0.y, r1.w + ld_structured r3.x, r2.x, l(16), g0.xxxx + ishl r2.x, r1.w, l(1) + ishl r2.x, r3.x, r2.x + or r12.w, r2.x, r12.w + iadd r1.w, r1.w, l(1) + endloop + else + ieq r0.z, r0.w, l(3) + if_nz r0.z + ishl r0.z, r1.y, l(4) + iadd r0.z, r0.z, l(8) + ld_structured r2.xyz, r0.y, l(68), g0.xyzx + ishl r3.x, r2.x, l(9) + ishl r3.y, r2.y, l(5) + ishl r3.z, r2.z, l(1) + and r3.xyz, r3.xyzx, l(0x0001fc00, 8128, 508, 0) + or r0.z, r0.z, r3.x + ld_structured r4.xyz, r0.y, l(84), g0.xyzx + ishl r5.x, r4.x, l(16) + ishl r5.y, r4.y, l(12) + ishl r5.z, r4.z, l(8) + and r5.xyz, r5.xyzx, l(0x00fe0000, 0x000fe000, 0x0000fe00, 0) + or r0.z, r0.z, r5.x + iadd r1.w, r0.y, l(1) + ld_structured r6.xyz, r1.w, l(68), g0.xyzx + ishl r7.x, r6.x, l(23) + ishl r7.y, r6.y, l(19) + ishl r7.z, r6.z, l(15) + and r7.xyz, r7.xyzx, l(0x7f000000, 0x07f00000, 0x007f0000, 0) + or r0.z, r0.z, r7.x + ld_structured r8.xyz, r1.w, l(84), g0.xyzx + ishl r9.x, r8.x, l(30) + ishl r9.y, r8.y, l(26) + ishl r9.z, r8.z, l(22) + and r9.xyz, r9.xyzx, l(0x80000000, 0xf8000000, 0x3f800000, 0) + or r12.x, r0.z, r9.x + ld_structured r10.xy, r1.w, l(84), g0.xyxx + ushr r11.x, r10.x, l(2) + ushr r11.y, r10.y, l(6) + and r2.xw, r11.xxxy, l(63, 0, 0, 3) + iadd r2.xy, r3.yzyy, r2.xwxx + iadd r2.xy, r5.yzyy, r2.xyxx + iadd r2.xy, r7.yzyy, r2.xyxx + iadd r2.xy, r9.yzyy, r2.xyxx + ld_structured r3.x, r0.y, l(68), g0.xxxx + ishl r0.z, r3.x, l(30) + and r0.z, r0.z, l(0x40000000) + iadd r0.z, r0.z, r2.y + ld_structured r3.x, r0.y, l(84), g0.xxxx + ishl r2.y, r3.x, l(31) + iadd r12.z, r0.z, r2.y + ld_structured r3.x, r1.w, l(68), g0.xxxx + and r0.z, r3.x, l(1) + ld_structured r3.x, r1.w, l(84), g0.xxxx + ishl r1.w, r3.x, l(1) + and r1.w, r1.w, l(2) + iadd r0.z, r0.z, r1.w + ld_structured r3.x, r0.y, l(16), g0.xxxx + ishl r1.w, r3.x, l(2) + iadd r0.z, r0.z, r1.w + mov r1.w, r0.z + mov r2.y, l(1) + loop + ult r2.z, icb[r1.y + 128].y, r2.y + breakc_nz r2.z + iadd r2.z, r0.y, r2.y + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r2.y, l(1) + iadd r2.z, r2.z, l(1) + ishl r2.z, r3.x, r2.z + or r1.w, r1.w, r2.z + iadd r2.y, r2.y, l(1) + endloop + mov r12.w, r1.w + mov r0.z, r2.y + loop + uge r2.z, r0.z, l(16) + breakc_nz r2.z + iadd r2.z, r0.z, r0.y + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r2.z, r0.z, l(1) + ishl r2.z, r3.x, r2.z + or r12.w, r2.z, r12.w + iadd r0.z, r0.z, l(1) + endloop + mov r12.y, r2.x + else + ieq r0.z, r0.w, l(4) + if_nz r0.z + ishl r0.z, r1.z, l(5) + and r0.z, r0.z, l(96) + iadd r0.z, r0.z, l(16) + ishl r1.x, r1.x, l(7) + iadd r0.z, r0.z, r1.x + ld_structured r2.xyzw, r0.y, l(68), g0.xyzw + ishl r3.x, r2.x, l(5) + ishl r3.y, r2.y, l(15) + ishl r3.z, r2.z, l(25) + ishl r3.w, r2.w, l(4) + and r2.xyzw, r3.xyzw, l(7936, 0x007c0000, 0xf0000000, 4032) + iadd r0.z, r0.z, r2.x + ld_structured r3.xyzw, r0.y, l(84), g0.xyzw + ishl r4.xz, r3.xxwx, l(10) + ishl r4.y, r3.y, l(20) + and r3.xyw, r4.xyxz, l(0x0003e000, 0x0f800000, 0, 0x0003f000) + iadd r0.z, r0.z, r3.x + iadd r0.z, r2.y, r0.z + iadd r0.z, r3.y, r0.z + iadd r12.x, r2.z, r0.z + ld_structured r4.x, r0.y, l(76), g0.xxxx + ushr r0.z, r4.x, l(7) + and r0.z, r0.z, l(1) + ushr r1.x, r3.z, l(2) + and r1.x, r1.x, l(62) + iadd r0.z, r0.z, r1.x + iadd r0.z, r2.w, r0.z + iadd r0.z, r3.w, r0.z + ld_structured r2.xy, r0.y, l(16), g0.xyxx + ishl r3.x, r2.x, l(18) + ishl r3.y, r2.y, l(17) + and r1.xw, r3.xxxy, l(0x00040000, 0, 0, 0x00060000) + iadd r0.z, r0.z, r1.x + iadd r2.xyzw, r0.yyyy, l(1, 2, 3, 4) + ld_structured r3.xy, r2.x, l(16), g0.xyxx + ishl r3.xy, r3.xyxx, l(19) + iadd r0.z, r0.z, r3.x + ld_structured r4.xy, r2.y, l(16), g0.xyxx + ishl r1.x, r4.x, l(21) + ishl r2.x, r4.y, l(22) + or r0.z, r0.z, r1.x + ld_structured r4.xy, r2.z, l(16), g0.xyxx + ishl r1.x, r4.x, l(23) + ishl r2.y, r4.y, l(25) + or r0.z, r0.z, r1.x + ld_structured r4.xy, r2.w, l(16), g0.xyxx + ishl r1.x, r4.x, l(25) + ishl r2.z, r4.y, l(28) + or r0.z, r0.z, r1.x + iadd r4.xyzw, r0.yyyy, l(5, 6, 7, 8) + ld_structured r5.xy, r4.x, l(16), g0.xyxx + ishl r1.x, r5.x, l(27) + ishl r2.w, r5.y, l(31) + or r0.z, r0.z, r1.x + ld_structured r5.xy, r4.y, l(16), g0.xyxx + ishl r1.x, r5.x, l(29) + ishl r3.x, r5.y, l(2) + or r0.z, r0.z, r1.x + ld_structured r5.xy, r4.z, l(16), g0.xyxx + ishl r1.x, r5.x, l(31) + ishl r3.z, r5.y, l(5) + or r12.y, r0.z, r1.x + ld_structured r5.x, r4.z, l(16), g0.xxxx + ushr r0.z, r5.x, l(1) + ld_structured r5.xy, r4.w, l(16), g0.xyxx + ishl r1.x, r5.x, l(1) + ishl r3.w, r5.y, l(8) + or r0.z, r0.z, r1.x + iadd r5.xyzw, r0.yyyy, l(9, 10, 11, 12) + ld_structured r6.xy, r5.x, l(16), g0.xyxx + ishl r1.x, r6.x, l(3) + ishl r4.y, r6.y, l(11) + or r0.z, r0.z, r1.x + ld_structured r6.xy, r5.y, l(16), g0.xyxx + ishl r1.x, r6.x, l(5) + ishl r4.z, r6.y, l(14) + or r0.z, r0.z, r1.x + ld_structured r6.xy, r5.z, l(16), g0.xyxx + ishl r1.x, r6.x, l(7) + ishl r4.w, r6.y, l(17) + or r0.z, r0.z, r1.x + ld_structured r5.xy, r5.w, l(16), g0.xyxx + ishl r1.x, r5.x, l(9) + ishl r5.x, r5.y, l(20) + or r0.z, r0.z, r1.x + iadd r5.yzw, r0.yyyy, l(0, 13, 14, 15) + ld_structured r6.xy, r5.y, l(16), g0.xyxx + ishl r1.x, r6.x, l(11) + ishl r5.y, r6.y, l(23) + or r0.z, r0.z, r1.x + ld_structured r6.xy, r5.z, l(16), g0.xyxx + ishl r1.x, r6.x, l(13) + ishl r5.z, r6.y, l(26) + or r0.z, r0.z, r1.x + ld_structured r6.xy, r5.w, l(16), g0.xyxx + ishl r1.x, r6.x, l(15) + ishl r5.w, r6.y, l(29) + or r0.z, r0.z, r1.x + or r0.z, r1.w, r0.z + or r0.z, r3.y, r0.z + or r0.z, r2.x, r0.z + or r0.z, r2.y, r0.z + or r0.z, r2.z, r0.z + or r12.z, r2.w, r0.z + ld_structured r2.x, r4.x, l(20), g0.xxxx + ushr r0.z, r2.x, l(1) + or r0.z, r3.x, r0.z + or r0.z, r3.z, r0.z + or r0.z, r3.w, r0.z + or r0.z, r4.y, r0.z + or r0.z, r4.z, r0.z + or r0.z, r4.w, r0.z + or r0.z, r5.x, r0.z + or r0.z, r5.y, r0.z + or r0.z, r5.z, r0.z + or r12.w, r5.w, r0.z + else + ieq r0.z, r0.w, l(5) + if_nz r0.z + ishl r0.z, r1.z, l(6) + iadd r0.z, r0.z, l(32) + ld_structured r2.xyzw, r0.y, l(68), g0.xyzw + ishl r3.x, r2.x, l(7) + ishl r3.y, r2.y, l(21) + ishl r3.z, r2.z, l(3) + ishl r1.x, r2.w, l(18) + and r2.xyz, r3.xyzx, l(0x00007f00, 0x1fc00000, 2032, 0) + or r0.z, r0.z, r2.x + ld_structured r3.xyzw, r0.y, l(84), g0.xyzw + ishl r4.x, r3.x, l(14) + ishl r4.y, r3.y, l(28) + ishl r4.z, r3.z, l(10) + ishl r1.z, r3.w, l(26) + and r3.xyz, r4.xyzx, l(0x003f8000, 0xe0000000, 0x0003f800, 0) + or r0.z, r0.z, r3.x + or r0.z, r2.y, r0.z + or r12.x, r3.y, r0.z + ld_structured r4.x, r0.y, l(88), g0.xxxx + ushr r0.z, r4.x, l(4) + and r0.z, r0.z, l(15) + iadd r0.z, r2.z, r0.z + iadd r0.z, r3.z, r0.z + iadd r0.z, r1.x, r0.z + or r12.y, r1.z, r0.z + ld_structured r2.x, r0.y, l(96), g0.xxxx + ushr r0.z, r2.x, l(6) + ld_structured r2.xy, r0.y, l(16), g0.xyxx + ishl r1.x, r2.x, l(2) + ishl r1.z, r2.y, l(1) + or r0.z, r0.z, r1.x + iadd r2.xyzw, r0.yyyy, l(1, 2, 3, 4) + ld_structured r3.xy, r2.x, l(16), g0.xyxx + ishl r1.x, r3.x, l(3) + ishl r1.w, r3.y, l(2) + or r0.z, r0.z, r1.x + ld_structured r3.xy, r2.y, l(16), g0.xyxx + ishl r1.x, r3.x, l(5) + ishl r2.x, r3.y, l(4) + or r0.z, r0.z, r1.x + ld_structured r3.xy, r2.z, l(16), g0.xyxx + ishl r1.x, r3.x, l(7) + ishl r2.y, r3.y, l(6) + or r0.z, r0.z, r1.x + ld_structured r3.xy, r2.w, l(16), g0.xyxx + ishl r1.x, r3.x, l(9) + ishl r2.z, r3.y, l(8) + or r0.z, r0.z, r1.x + iadd r3.xyzw, r0.yyyy, l(5, 6, 7, 8) + ld_structured r4.xy, r3.x, l(16), g0.xyxx + ishl r1.x, r4.x, l(11) + ishl r2.w, r4.y, l(10) + or r0.z, r0.z, r1.x + ld_structured r4.xy, r3.y, l(16), g0.xyxx + ishl r1.x, r4.x, l(13) + ishl r3.x, r4.y, l(12) + or r0.z, r0.z, r1.x + ld_structured r4.xy, r3.z, l(16), g0.xyxx + ishl r1.x, r4.x, l(15) + ishl r3.y, r4.y, l(14) + or r0.z, r0.z, r1.x + ld_structured r4.xy, r3.w, l(16), g0.xyxx + ishl r1.x, r4.x, l(17) + ishl r3.z, r4.y, l(16) + or r0.z, r0.z, r1.x + iadd r4.xyzw, r0.yyyy, l(9, 10, 11, 12) + ld_structured r5.xy, r4.x, l(16), g0.xyxx + ishl r1.x, r5.x, l(19) + ishl r3.w, r5.y, l(18) + or r0.z, r0.z, r1.x + ld_structured r5.xy, r4.y, l(16), g0.xyxx + ishl r1.x, r5.x, l(21) + ishl r4.x, r5.y, l(20) + or r0.z, r0.z, r1.x + ld_structured r5.xy, r4.z, l(16), g0.xyxx + ishl r1.x, r5.x, l(23) + ishl r4.y, r5.y, l(22) + or r0.z, r0.z, r1.x + ld_structured r5.xy, r4.w, l(16), g0.xyxx + ishl r1.x, r5.x, l(25) + ishl r4.z, r5.y, l(24) + or r0.z, r0.z, r1.x + iadd r5.xyz, r0.yyyy, l(13, 14, 15, 0) + ld_structured r6.xy, r5.x, l(16), g0.xyxx + ishl r1.x, r6.x, l(27) + ishl r4.w, r6.y, l(26) + or r0.z, r0.z, r1.x + ld_structured r6.xy, r5.y, l(16), g0.xyxx + ishl r1.x, r6.x, l(29) + ishl r5.x, r6.y, l(28) + or r0.z, r0.z, r1.x + ld_structured r6.xy, r5.z, l(16), g0.xyxx + ishl r1.x, r6.x, l(31) + ishl r5.y, r6.y, l(30) + or r12.z, r0.z, r1.x + ld_structured r6.x, r5.z, l(16), g0.xxxx + ushr r0.z, r6.x, l(1) + or r0.z, r1.z, r0.z + or r0.z, r1.w, r0.z + or r0.z, r2.x, r0.z + or r0.z, r2.y, r0.z + or r0.z, r2.z, r0.z + or r0.z, r2.w, r0.z + or r0.z, r3.x, r0.z + or r0.z, r3.y, r0.z + or r0.z, r3.z, r0.z + or r0.z, r3.w, r0.z + or r0.z, r4.x, r0.z + or r0.z, r4.y, r0.z + or r0.z, r4.z, r0.z + or r0.z, r4.w, r0.z + or r0.z, r5.x, r0.z + or r12.w, r5.y, r0.z + else + ieq r0.z, r0.w, l(6) + if_nz r0.z + ld_structured r2.xyzw, r0.y, l(68), g0.xyzw + ishl r3.x, r2.x, l(6) + ishl r3.y, r2.y, l(20) + ishl r3.z, r2.z, l(2) + ishl r3.w, r2.w, l(16) + and r2.xyzw, r3.xyzw, l(0x00003f80, 0x0fe00000, 1016, 0x00fe0000) + iadd r0.z, r2.x, l(64) + ld_structured r3.xyzw, r0.y, l(84), g0.xyzw + ishl r4.x, r3.x, l(13) + ishl r4.y, r3.y, l(27) + ishl r4.z, r3.z, l(9) + ishl r4.w, r3.w, l(23) + and r3.xyzw, r4.xyzw, l(0x001fc000, 0xf0000000, 0x0001fc00, 0x7f000000) + iadd r0.z, r0.z, r3.x + iadd r0.z, r2.y, r0.z + iadd r12.x, r3.y, r0.z + ld_structured r4.xy, r0.y, l(84), g0.xyxx + ushr r0.z, r4.y, l(5) + and r0.z, r0.z, l(7) + iadd r0.z, r2.z, r0.z + iadd r0.z, r3.z, r0.z + iadd r0.z, r2.w, r0.z + iadd r0.z, r3.w, r0.z + ld_structured r2.x, r0.y, l(68), g0.xxxx + ishl r0.w, r2.x, l(31) + iadd r12.y, r0.w, r0.z + and r0.z, r4.x, l(1) + ld_structured r2.x, r0.y, l(16), g0.xxxx + ishl r0.w, r2.x, l(1) + iadd r0.z, r0.w, r0.z + iadd r2.xyzw, r0.yyyy, l(1, 2, 3, 4) + ld_structured r3.x, r2.x, l(16), g0.xxxx + ishl r0.w, r3.x, l(4) + or r0.z, r0.w, r0.z + ld_structured r3.x, r2.y, l(16), g0.xxxx + ishl r0.w, r3.x, l(8) + or r0.z, r0.w, r0.z + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r0.w, r3.x, l(12) + or r0.z, r0.w, r0.z + ld_structured r2.x, r2.w, l(16), g0.xxxx + ishl r0.w, r2.x, l(16) + or r0.z, r0.w, r0.z + iadd r2.xyzw, r0.yyyy, l(5, 6, 7, 8) + ld_structured r3.x, r2.x, l(16), g0.xxxx + ishl r0.w, r3.x, l(20) + or r0.z, r0.w, r0.z + ld_structured r3.x, r2.y, l(16), g0.xxxx + ishl r0.w, r3.x, l(24) + or r0.z, r0.w, r0.z + ld_structured r3.x, r2.z, l(16), g0.xxxx + ishl r0.w, r3.x, l(28) + or r12.z, r0.w, r0.z + ld_structured r2.x, r2.w, l(16), g0.xxxx + iadd r3.xyzw, r0.yyyy, l(9, 10, 11, 12) + ld_structured r4.x, r3.x, l(16), g0.xxxx + ishl r0.z, r4.x, l(4) + or r0.z, r0.z, r2.x + ld_structured r2.x, r3.y, l(16), g0.xxxx + ishl r0.w, r2.x, l(8) + or r0.z, r0.w, r0.z + ld_structured r2.x, r3.z, l(16), g0.xxxx + ishl r0.w, r2.x, l(12) + or r0.z, r0.w, r0.z + ld_structured r2.x, r3.w, l(16), g0.xxxx + ishl r0.w, r2.x, l(16) + or r0.z, r0.w, r0.z + iadd r1.xzw, r0.yyyy, l(13, 0, 14, 15) + ld_structured r2.x, r1.x, l(16), g0.xxxx + ishl r0.w, r2.x, l(20) + or r0.z, r0.w, r0.z + ld_structured r2.x, r1.z, l(16), g0.xxxx + ishl r0.w, r2.x, l(24) + or r0.z, r0.w, r0.z + ld_structured r2.x, r1.w, l(16), g0.xxxx + ishl r0.w, r2.x, l(28) + or r12.w, r0.w, r0.z + else + ishl r0.z, r1.y, l(8) + iadd r0.z, r0.z, l(128) + ld_structured r2.xyzw, r0.y, l(68), g0.xyzw + ishl r3.x, r2.x, l(11) + ishl r3.y, r2.z, l(19) + ishl r3.z, r2.w, l(7) + and r1.xzw, r3.xxyz, l(0x0007c000, 0, 0x07c00000, 0x00007c00) + or r0.z, r0.z, r1.x + ld_structured r3.xyzw, r0.y, l(84), g0.xyzw + ishl r4.x, r3.x, l(16) + ishl r4.y, r3.y, l(4) + ishl r4.z, r3.z, l(24) + ishl r4.w, r3.w, l(12) + and r4.xyzw, r4.xyzw, l(0x00f80000, 3968, 0xf8000000, 0x000f8000) + or r0.z, r0.z, r4.x + iadd r0.w, r0.y, l(1) + ld_structured r5.xyzw, r0.w, l(68), g0.xyzw + ishl r6.x, r5.x, l(21) + ishl r6.y, r5.y, l(9) + ishl r6.z, r5.w, l(17) + and r6.xyz, r6.xyzx, l(0x1f000000, 0x0001f000, 0x01f00000, 0) + or r0.z, r0.z, r6.x + ld_structured r7.xyzw, r0.w, l(84), g0.xyzw + ishl r8.x, r7.x, l(26) + ishl r8.y, r7.y, l(14) + ishl r8.z, r7.z, l(2) + ishl r8.w, r7.w, l(22) + and r8.xyzw, r8.xyzw, l(0xe0000000, 0x003e0000, 992, 0x3e000000) + or r12.x, r0.z, r8.x + ld_structured r9.x, r0.w, l(84), g0.xxxx + ushr r10.x, r9.x, l(6) + ushr r10.y, r9.x, l(1) + and r6.xw, r10.xxxy, l(3, 0, 0, 2) + ushr r0.z, r2.y, l(1) + and r0.z, r0.z, l(124) + iadd r0.z, r0.z, r6.x + iadd r0.z, r4.y, r0.z + iadd r0.z, r6.y, r0.z + iadd r0.z, r8.y, r0.z + iadd r0.z, r1.z, r0.z + iadd r12.y, r4.z, r0.z + ushr r0.z, r5.z, l(3) + and r0.z, r0.z, l(31) + iadd r0.z, r8.z, r0.z + iadd r0.z, r1.w, r0.z + iadd r0.z, r4.w, r0.z + iadd r0.z, r6.z, r0.z + iadd r0.z, r8.w, r0.z + ld_structured r2.x, r0.y, l(68), g0.xxxx + ishl r1.x, r2.x, l(28) + and r1.x, r1.x, l(0x40000000) + iadd r0.z, r0.z, r1.x + ld_structured r2.x, r0.y, l(84), g0.xxxx + ishl r1.x, r2.x, l(29) + and r1.x, r1.x, l(0x80000000) + iadd r12.z, r0.z, r1.x + ld_structured r2.x, r0.w, l(68), g0.xxxx + ushr r0.z, r2.x, l(2) + and r0.z, r0.z, l(1) + iadd r0.z, r6.w, r0.z + ld_structured r2.x, r0.y, l(16), g0.xxxx + ishl r0.w, r2.x, l(2) + iadd r0.z, r0.w, r0.z + mov r0.w, r0.z + mov r1.x, l(1) + loop + ult r1.z, icb[r1.y + 128].y, r1.x + breakc_nz r1.z + iadd r1.z, r0.y, r1.x + ld_structured r2.x, r1.z, l(16), g0.xxxx + ishl r1.z, r1.x, l(1) + iadd r1.z, r1.z, l(1) + ishl r1.z, r2.x, r1.z + or r0.w, r0.w, r1.z + iadd r1.x, r1.x, l(1) + endloop + mov r12.w, r0.w + mov r0.z, r1.x + loop + uge r1.y, r0.z, l(16) + breakc_nz r1.y + iadd r1.y, r0.z, r0.y + ld_structured r2.x, r1.y, l(16), g0.xxxx + ishl r1.y, r0.z, l(1) + ishl r1.y, r2.x, r1.y + or r12.w, r1.y, r12.w + iadd r0.z, r0.z, l(1) + endloop + endif + endif + endif + endif + endif + endif + endif + store_structured u0.xyzw, r0.x, l(0), r12.xyzw +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC7Encode_EncodeBlockCS[] = +{ + 68, 88, 66, 67, 38, 175, + 165, 204, 73, 182, 127, 102, + 182, 246, 162, 152, 80, 235, + 28, 253, 1, 0, 0, 0, + 200, 193, 0, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 116, 193, 0, 0, + 64, 0, 5, 0, 93, 48, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 2, 4, + 0, 0, 204, 204, 0, 0, + 80, 80, 104, 170, 15, 0, + 0, 0, 0, 0, 0, 0, + 136, 136, 0, 0, 64, 80, + 90, 106, 15, 0, 0, 0, + 0, 0, 0, 0, 238, 238, + 0, 0, 0, 66, 90, 90, + 15, 0, 0, 0, 0, 0, + 0, 0, 200, 236, 0, 0, + 168, 160, 80, 84, 15, 0, + 0, 0, 0, 0, 0, 0, + 128, 200, 0, 0, 0, 0, + 165, 165, 15, 0, 0, 0, + 0, 0, 0, 0, 236, 254, + 0, 0, 80, 80, 160, 160, + 15, 0, 0, 0, 0, 0, + 0, 0, 200, 254, 0, 0, + 160, 160, 85, 85, 15, 0, + 0, 0, 0, 0, 0, 0, + 128, 236, 0, 0, 80, 80, + 90, 90, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 200, + 0, 0, 0, 0, 85, 170, + 15, 0, 0, 0, 0, 0, + 0, 0, 236, 255, 0, 0, + 0, 85, 85, 170, 15, 0, + 0, 0, 0, 0, 0, 0, + 128, 254, 0, 0, 0, 85, + 170, 170, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 232, + 0, 0, 144, 144, 144, 144, + 15, 0, 0, 0, 0, 0, + 0, 0, 232, 255, 0, 0, + 148, 148, 148, 148, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 164, 164, + 164, 164, 15, 0, 0, 0, + 0, 0, 0, 0, 240, 255, + 0, 0, 80, 148, 165, 169, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 240, 0, 0, + 80, 66, 10, 42, 15, 0, + 0, 0, 0, 0, 0, 0, + 16, 247, 0, 0, 64, 80, + 148, 165, 15, 0, 0, 0, + 0, 0, 0, 0, 142, 0, + 0, 0, 84, 80, 66, 10, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 113, 0, 0, + 0, 165, 165, 165, 8, 0, + 0, 0, 0, 0, 0, 0, + 206, 8, 0, 0, 160, 160, + 160, 85, 2, 0, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 0, 84, 84, 168, 168, + 2, 0, 0, 0, 0, 0, + 0, 0, 16, 115, 0, 0, + 64, 64, 106, 106, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 49, 0, 0, 0, 80, + 164, 164, 8, 0, 0, 0, + 0, 0, 0, 0, 206, 140, + 0, 0, 0, 5, 26, 26, + 15, 0, 0, 0, 0, 0, + 0, 0, 140, 8, 0, 0, + 164, 164, 80, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 16, 49, 0, 0, 144, 144, + 165, 170, 8, 0, 0, 0, + 0, 0, 0, 0, 102, 102, + 0, 0, 20, 105, 105, 20, + 2, 0, 0, 0, 0, 0, + 0, 0, 108, 54, 0, 0, + 0, 20, 105, 105, 2, 0, + 0, 0, 0, 0, 0, 0, + 232, 23, 0, 0, 160, 133, + 133, 160, 8, 0, 0, 0, + 0, 0, 0, 0, 240, 15, + 0, 0, 20, 20, 130, 170, + 8, 0, 0, 0, 0, 0, + 0, 0, 142, 113, 0, 0, + 80, 164, 164, 80, 2, 0, + 0, 0, 0, 0, 0, 0, + 156, 57, 0, 0, 0, 2, + 90, 106, 2, 0, 0, 0, + 0, 0, 0, 0, 170, 170, + 0, 0, 0, 128, 165, 169, + 15, 0, 0, 0, 0, 0, + 0, 0, 240, 240, 0, 0, + 168, 160, 144, 80, 15, 0, + 0, 0, 0, 0, 0, 0, + 90, 90, 0, 0, 80, 144, + 160, 168, 6, 0, 0, 0, + 0, 0, 0, 0, 204, 51, + 0, 0, 36, 36, 36, 36, + 8, 0, 0, 0, 0, 0, + 0, 0, 60, 60, 0, 0, + 0, 85, 170, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 170, 85, 0, 0, 36, 73, + 146, 36, 8, 0, 0, 0, + 0, 0, 0, 0, 150, 150, + 0, 0, 36, 146, 73, 36, + 15, 0, 0, 0, 0, 0, + 0, 0, 90, 165, 0, 0, + 80, 10, 165, 80, 15, 0, + 0, 0, 0, 0, 0, 0, + 206, 115, 0, 0, 80, 165, + 10, 80, 2, 0, 0, 0, + 0, 0, 0, 0, 200, 19, + 0, 0, 68, 68, 170, 170, + 8, 0, 0, 0, 0, 0, + 0, 0, 76, 50, 0, 0, + 0, 0, 102, 102, 2, 0, + 0, 0, 0, 0, 0, 0, + 220, 59, 0, 0, 160, 165, + 160, 165, 2, 0, 0, 0, + 0, 0, 0, 0, 150, 105, + 0, 0, 160, 80, 160, 80, + 2, 0, 0, 0, 0, 0, + 0, 0, 60, 195, 0, 0, + 40, 105, 40, 105, 15, 0, + 0, 0, 0, 0, 0, 0, + 102, 153, 0, 0, 68, 170, + 170, 68, 15, 0, 0, 0, + 0, 0, 0, 0, 96, 6, + 0, 0, 0, 102, 102, 102, + 6, 0, 0, 0, 0, 0, + 0, 0, 114, 2, 0, 0, + 68, 68, 68, 170, 6, 0, + 0, 0, 0, 0, 0, 0, + 228, 4, 0, 0, 168, 84, + 168, 84, 2, 0, 0, 0, + 0, 0, 0, 0, 64, 78, + 0, 0, 128, 149, 128, 149, + 6, 0, 0, 0, 0, 0, + 0, 0, 32, 39, 0, 0, + 0, 150, 150, 150, 8, 0, + 0, 0, 0, 0, 0, 0, + 54, 201, 0, 0, 168, 84, + 84, 168, 15, 0, 0, 0, + 0, 0, 0, 0, 108, 147, + 0, 0, 128, 149, 149, 128, + 15, 0, 0, 0, 0, 0, + 0, 0, 198, 57, 0, 0, + 20, 20, 20, 170, 2, 0, + 0, 0, 0, 0, 0, 0, + 156, 99, 0, 0, 0, 0, + 150, 150, 2, 0, 0, 0, + 0, 0, 0, 0, 54, 147, + 0, 0, 20, 20, 170, 170, + 15, 0, 0, 0, 0, 0, + 0, 0, 198, 156, 0, 0, + 160, 80, 80, 160, 15, 0, + 0, 0, 0, 0, 0, 0, + 126, 129, 0, 0, 160, 165, + 165, 160, 15, 0, 0, 0, + 0, 0, 0, 0, 24, 231, + 0, 0, 0, 0, 0, 150, + 15, 0, 0, 0, 0, 0, + 0, 0, 240, 204, 0, 0, + 128, 64, 128, 64, 15, 0, + 0, 0, 0, 0, 0, 0, + 204, 15, 0, 0, 168, 169, + 168, 169, 2, 0, 0, 0, + 0, 0, 0, 0, 68, 119, + 0, 0, 68, 170, 170, 170, + 2, 0, 0, 0, 0, 0, + 0, 0, 34, 238, 0, 0, + 84, 82, 74, 42, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 8, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 3, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 10, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 10, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 8, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 10, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 10, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 8, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 9, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 10, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 8, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 8, 0, 0, 0, + 11, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 13, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 15, 0, + 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 13, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 15, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 15, 0, 0, 0, + 14, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 15, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 6, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 6, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 10, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 10, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 10, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 13, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 12, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 162, 0, 0, 4, + 0, 112, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 0, + 158, 0, 0, 4, 0, 224, + 17, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 95, 0, + 0, 2, 0, 64, 2, 0, + 95, 0, 0, 2, 18, 16, + 2, 0, 104, 0, 0, 2, + 15, 0, 0, 0, 160, 0, + 0, 5, 0, 240, 17, 0, + 0, 0, 0, 0, 100, 0, + 0, 0, 64, 0, 0, 0, + 155, 0, 0, 4, 64, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 6, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 16, + 2, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 80, 0, + 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 1, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 48, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 70, 114, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 127, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 6, 112, 16, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 79, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 16, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 2, 0, 0, 0, + 78, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 0, 208, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 35, 0, 0, 11, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 127, 67, 0, 0, 127, 67, + 28, 0, 0, 5, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 84, 0, 0, 10, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 32, 0, 0, 10, 50, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 4, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 32, 0, 0, 10, + 114, 0, 16, 0, 4, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 194, 0, + 16, 0, 5, 0, 0, 0, + 166, 10, 16, 0, 4, 0, + 0, 0, 246, 11, 16, 0, + 3, 0, 0, 0, 166, 14, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 9, + 226, 0, 16, 0, 5, 0, + 0, 0, 86, 5, 16, 0, + 4, 0, 0, 0, 246, 6, + 16, 0, 3, 0, 0, 0, + 86, 14, 16, 0, 5, 0, + 0, 0, 55, 0, 0, 9, + 242, 0, 16, 0, 4, 0, + 0, 0, 6, 0, 16, 0, + 4, 0, 0, 0, 118, 2, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 55, 0, 0, 9, + 242, 0, 16, 0, 3, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 30, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 192, 255, 255, 255, + 31, 0, 4, 3, 10, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 3, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 8, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 144, 144, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 32, 0, 0, 10, 98, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 32, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 5, 0, 0, 0, + 6, 0, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 1, 0, 0, 7, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 6, 0, 16, 0, + 4, 0, 0, 0, 55, 0, + 0, 12, 242, 0, 16, 0, + 5, 0, 0, 0, 86, 5, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 1, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 84, 0, 0, 7, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 3, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 4, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 18, 0, 16, 0, + 5, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 84, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 83, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 58, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 3, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 4, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 18, 0, + 16, 0, 5, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 79, 0, + 0, 10, 50, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 3, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 4, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 5, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 32, 0, + 0, 10, 194, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 3, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 6, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 85, 0, 0, 8, + 66, 0, 16, 0, 3, 0, + 0, 0, 10, 144, 144, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 8, 18, 0, + 16, 0, 7, 0, 0, 0, + 26, 144, 144, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 32, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 32, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 12, + 242, 0, 16, 0, 9, 0, + 0, 0, 6, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 1, 0, 0, 7, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 7, 0, 0, 0, + 60, 0, 0, 7, 50, 0, + 16, 0, 8, 0, 0, 0, + 214, 5, 16, 0, 8, 0, + 0, 0, 134, 0, 16, 0, + 8, 0, 0, 0, 32, 0, + 0, 7, 66, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 32, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 12, 242, 0, 16, 0, + 10, 0, 0, 0, 166, 10, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 1, 0, + 0, 7, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 12, + 242, 0, 16, 0, 10, 0, + 0, 0, 86, 5, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 1, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 86, 5, + 16, 0, 8, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 9, 0, 0, 0, + 6, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 6, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 7, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 6, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 7, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 66, 0, 16, 0, 3, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 84, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 6, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 7, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 84, 0, + 0, 7, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 83, 0, + 0, 7, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 3, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 6, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 7, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 58, 0, 16, 0, + 3, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 6, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 8, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 144, + 144, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 8, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 144, 144, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 32, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 9, 0, 0, 0, + 6, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 70, 14, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 7, 0, 0, 0, + 6, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 60, 0, 0, 7, 50, 0, + 16, 0, 8, 0, 0, 0, + 214, 5, 16, 0, 8, 0, + 0, 0, 134, 0, 16, 0, + 8, 0, 0, 0, 32, 0, + 0, 10, 242, 0, 16, 0, + 10, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 7, 0, + 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 11, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 70, 14, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 12, 242, 0, + 16, 0, 12, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 12, + 242, 0, 16, 0, 10, 0, + 0, 0, 166, 10, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 1, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 166, 10, + 16, 0, 3, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 10, 0, 0, 0, + 86, 5, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 6, 0, 0, 0, + 86, 5, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 9, 0, 0, 0, + 6, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 6, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 7, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 6, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 7, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 84, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 6, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 7, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 84, 0, + 0, 7, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 83, 0, + 0, 7, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 3, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 6, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 7, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 0, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 3, 0, + 0, 0, 32, 0, 0, 10, + 226, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 98, 0, + 16, 0, 3, 0, 0, 0, + 6, 1, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 6, 0, 16, 0, 3, 0, + 0, 0, 150, 5, 16, 0, + 3, 0, 0, 0, 31, 0, + 0, 3, 58, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 0, + 30, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 6, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 30, 0, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 86, 5, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 255, 0, 0, 0, 54, 0, + 0, 8, 178, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 248, 7, 0, 0, 0, 0, + 0, 0, 248, 7, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 126, 0, + 0, 0, 126, 0, 0, 0, + 126, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 9, 0, + 0, 0, 6, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 126, 0, 0, 0, 126, 0, + 0, 0, 126, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 86, 5, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 255, 0, 0, 0, 54, 0, + 0, 8, 178, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 254, 1, 0, 0, 0, 0, + 0, 0, 254, 1, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 84, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 255, 0, + 0, 0, 54, 0, 0, 8, + 178, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 248, 7, + 0, 0, 0, 0, 0, 0, + 248, 7, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 254, 255, 255, 255, 254, 255, + 255, 255, 254, 255, 255, 255, + 0, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 254, 255, 255, 255, + 254, 255, 255, 255, 254, 255, + 255, 255, 0, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 8, 0, 0, 0, + 86, 5, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 54, 0, + 0, 5, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 54, 0, 0, 5, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 255, 0, 0, 0, 54, 0, + 0, 8, 178, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 255, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 84, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 252, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 10, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 84, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 4, 0, 0, 0, 198, 6, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 248, 0, + 0, 0, 252, 0, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 5, 0, 0, 0, 198, 6, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 10, 0, + 0, 0, 54, 0, 0, 5, + 114, 0, 16, 0, 8, 0, + 0, 0, 198, 2, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 254, 0, 0, 0, 254, 0, + 0, 0, 254, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 254, 0, 0, 0, + 254, 0, 0, 0, 254, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 254, 255, 255, 255, + 254, 255, 255, 255, 254, 255, + 255, 255, 254, 255, 255, 255, + 30, 0, 0, 7, 242, 0, + 16, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 254, 255, + 255, 255, 254, 255, 255, 255, + 254, 255, 255, 255, 254, 255, + 255, 255, 30, 0, 0, 7, + 242, 0, 16, 0, 4, 0, + 0, 0, 86, 5, 16, 0, + 3, 0, 0, 0, 198, 6, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 5, + 242, 0, 16, 0, 5, 0, + 0, 0, 198, 6, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 114, 0, 16, 0, + 8, 0, 0, 0, 198, 2, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 5, 146, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 6, 0, + 0, 0, 18, 0, 0, 1, + 30, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 84, 0, + 0, 10, 242, 0, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 85, 0, 0, 7, + 242, 0, 16, 0, 9, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 62, 0, 0, 0, 62, 0, + 0, 0, 62, 0, 0, 0, + 62, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 9, 0, 0, 0, 6, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 242, 0, 16, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 242, 0, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 4, 0, 0, 0, 54, 6, + 16, 0, 6, 0, 0, 0, + 54, 6, 16, 0, 10, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 84, 0, 0, 10, 242, 0, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 10, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 85, 0, + 0, 7, 242, 0, 16, 0, + 10, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 62, 0, 0, 0, + 62, 0, 0, 0, 62, 0, + 0, 0, 62, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 10, 0, 0, 0, + 86, 5, 16, 0, 3, 0, + 0, 0, 198, 9, 16, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 242, 0, 16, 0, + 8, 0, 0, 0, 134, 7, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 54, 0, + 0, 5, 114, 0, 16, 0, + 7, 0, 0, 0, 214, 6, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 5, 162, 0, + 16, 0, 4, 0, 0, 0, + 86, 1, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 40, 0, 0, 5, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 40, 0, 0, 5, + 130, 0, 16, 0, 9, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 10, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 79, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 0, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 10, 0, 0, 0, 6, 4, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 35, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 8, + 34, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 34, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 34, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 34, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 43, 0, 0, 5, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 28, 0, 0, 5, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 11, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 5, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 12, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 8, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 34, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 34, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 43, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 28, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 13, 0, 0, 0, + 166, 10, 16, 0, 2, 0, + 0, 0, 38, 13, 16, 0, + 4, 0, 0, 0, 134, 7, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 13, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 54, 0, 0, 5, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 14, 16, 0, 12, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 130, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 242, 0, 16, 0, + 11, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 18, 0, 0, 1, + 31, 0, 0, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 144, 144, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 6, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 144, + 144, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 38, 0, 0, 8, 0, 208, + 0, 0, 50, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 10, 0, 0, 0, + 70, 0, 16, 0, 10, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 35, 0, 0, 9, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 34, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 34, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 43, 0, 0, 5, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 28, 0, 0, 5, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 79, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 11, 0, 0, 0, + 86, 5, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 86, 5, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 5, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 6, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 8, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 21, 0, + 0, 1, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 2, 0, + 0, 0, 32, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 6, 0, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 15, 98, 0, 16, 0, + 3, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 98, 0, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 86, 6, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 98, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 86, 6, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 12, 50, 0, 16, 0, + 3, 0, 0, 0, 6, 0, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 150, 5, 16, 0, + 3, 0, 0, 0, 32, 0, + 0, 10, 242, 0, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 7, 0, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 8, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 144, 144, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 3, 16, 0, 2, 0, + 0, 0, 70, 3, 16, 0, + 4, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 85, 0, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 144, 144, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 8, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 128, 65, 0, 0, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 50, 0, 16, 0, 2, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 35, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 6, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 8, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 6, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 5, 0, 0, 0, 6, 4, + 16, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 33, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 33, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 34, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 43, 0, 0, 5, + 82, 0, 16, 0, 2, 0, + 0, 0, 6, 2, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 14, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 28, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 162, 0, 16, 0, 3, 0, + 0, 0, 6, 4, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 11, 0, + 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 78, 0, 0, 11, + 0, 208, 0, 0, 50, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 68, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79, 0, + 0, 10, 50, 0, 16, 0, + 7, 0, 0, 0, 214, 5, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 12, + 50, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 15, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 6, 0, + 0, 0, 55, 0, 0, 11, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 144, + 208, 0, 64, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 33, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 86, 1, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 34, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 43, 0, 0, 5, 50, 0, + 16, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 28, 0, + 0, 5, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 55, 0, + 0, 11, 18, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 10, 144, 208, 0, 64, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 9, 18, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 2, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 0, 16, 0, + 7, 0, 0, 0, 22, 5, + 16, 0, 7, 0, 0, 0, + 18, 0, 0, 1, 38, 0, + 0, 8, 0, 208, 0, 0, + 194, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 5, 0, 0, 0, 6, 4, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 6, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 6, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 98, 0, + 16, 0, 3, 0, 0, 0, + 6, 1, 16, 0, 4, 0, + 0, 0, 6, 1, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 35, 0, 0, 9, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 35, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 33, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 33, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 34, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 43, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 43, 0, 0, 5, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 14, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 28, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 78, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 79, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 11, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 0, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 31, 0, + 0, 3, 58, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 128, 255, 255, 255, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 224, 1, + 0, 0, 0, 0, 0, 224, + 0, 0, 224, 1, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 84, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 1, 0, 0, 10, + 146, 0, 16, 0, 2, 0, + 0, 0, 6, 4, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 30, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 10, 146, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 224, 1, 0, + 224, 1, 0, 0, 0, 0, + 0, 224, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 13, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 1, 0, 0, 10, 146, 0, + 16, 0, 4, 0, 0, 0, + 6, 4, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 30, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 9, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 224, 1, + 0, 224, 1, 0, 224, 1, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 10, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 30, 0, 0, 30, 0, + 0, 30, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 60, 0, 0, 7, 18, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 13, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 76, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 32, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 64, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 128, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 1, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 4, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 84, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 144, 208, 0, 128, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 48, 0, 0, 1, + 79, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 3, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 79, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 144, 208, 0, 128, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 48, 0, 0, 1, + 79, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 144, 208, 0, 128, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 3, 0, 4, 3, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 242, 255, 255, 255, 41, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 21, 0, 0, 1, + 54, 0, 0, 5, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 48, 0, + 0, 1, 79, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 144, 208, 0, + 128, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 3, 0, 4, 3, + 10, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 35, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 241, 255, 255, 255, + 41, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 54, 0, + 0, 5, 130, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 48, 0, 0, 1, + 80, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 3, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 240, 255, + 255, 255, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 18, 0, 0, 1, 32, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 82, 0, + 16, 0, 2, 0, 0, 0, + 6, 1, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 192, 15, 0, + 192, 15, 0, 0, 0, 0, + 0, 192, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 240, 3, + 0, 240, 3, 0, 240, 3, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 252, 0, 0, 252, 0, + 0, 252, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 63, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 92, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 1, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 2, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 18, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 32, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 26, 144, 208, 0, 128, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 15, 0, + 0, 0, 14, 0, 0, 0, + 13, 0, 0, 0, 12, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 11, 0, 0, 0, 10, 0, + 0, 0, 9, 0, 0, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 7, 0, 0, 0, 6, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 30, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 26, 144, + 208, 0, 128, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 3, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 15, 0, 0, 0, + 14, 0, 0, 0, 13, 0, + 0, 0, 12, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 11, 0, + 0, 0, 10, 0, 0, 0, + 9, 0, 0, 0, 8, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 14, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 7, 0, + 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 194, 0, 16, 0, 2, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 9, 34, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 26, 144, 208, 0, + 128, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 15, 0, 0, 0, 14, 0, + 0, 0, 13, 0, 0, 0, + 12, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 3, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 11, 0, 0, 0, + 10, 0, 0, 0, 9, 0, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 11, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 3, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 7, 0, 0, 0, + 6, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 30, 0, 0, 10, 194, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 30, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 15, 0, + 0, 0, 14, 0, 0, 0, + 13, 0, 0, 0, 12, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 29, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 11, 0, 0, 0, 10, 0, + 0, 0, 9, 0, 0, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 7, 0, 0, 0, 6, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 30, 0, + 0, 10, 194, 0, 16, 0, + 2, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 18, 0, + 0, 1, 32, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 254, + 255, 255, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 62, 0, 0, 128, 15, + 0, 0, 224, 3, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 192, 7, 0, + 0, 240, 1, 0, 0, 124, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 30, 0, + 0, 10, 146, 0, 16, 0, + 2, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 248, 0, + 0, 0, 62, 0, 0, 128, + 15, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 9, 0, 0, 0, 10, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 31, 0, 0, 192, 7, + 0, 0, 240, 1, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 224, 0, 0, + 0, 248, 0, 0, 0, 62, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 14, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 14, 0, + 0, 0, 26, 0, 16, 0, + 13, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 146, 0, + 16, 0, 3, 0, 0, 0, + 6, 4, 16, 0, 14, 0, + 0, 0, 2, 64, 0, 0, + 124, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 13, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 192, 30, 0, 0, 7, + 66, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 92, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 48, 0, 0, 1, + 79, 0, 0, 9, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 144, 208, 0, 128, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 3, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 48, 0, 0, 1, + 79, 0, 0, 9, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 144, 208, 0, 128, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 3, 0, 4, 3, 42, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 54, 0, + 0, 5, 130, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 48, 0, 0, 1, + 80, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 3, 0, + 4, 3, 10, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 18, 0, + 0, 1, 32, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 167, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 242, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 252, 1, 0, + 192, 31, 0, 0, 252, 1, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 254, 0, 0, 224, 15, 0, + 0, 254, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 114, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 127, 0, 0, 240, 7, + 0, 0, 127, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 84, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 9, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 22, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 128, 0, 0, + 0, 248, 0, 0, 128, 63, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 1, 0, + 0, 10, 146, 0, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 63, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 50, 0, 16, 0, 2, 0, + 0, 0, 150, 5, 16, 0, + 3, 0, 0, 0, 198, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 50, 0, + 16, 0, 2, 0, 0, 0, + 150, 5, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 50, 0, 16, 0, + 2, 0, 0, 0, 150, 5, + 16, 0, 7, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 50, 0, 16, 0, 2, 0, + 0, 0, 150, 5, 16, 0, + 9, 0, 0, 0, 70, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 30, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 84, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 84, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 48, 0, 0, 1, 79, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 144, + 208, 0, 128, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 3, 0, + 4, 3, 42, 0, 16, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 54, 0, 0, 5, + 130, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 42, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 54, 0, 0, 5, + 34, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 96, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 25, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 31, 0, 0, 0, 0, + 124, 0, 0, 0, 0, 240, + 192, 15, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 82, 0, 16, 0, 4, 0, + 0, 0, 6, 3, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 1, 0, + 0, 10, 178, 0, 16, 0, + 3, 0, 0, 0, 70, 8, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 224, + 3, 0, 0, 0, 128, 15, + 0, 0, 0, 0, 0, 240, + 3, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 76, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 62, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 1, 0, 0, 10, 146, 0, + 16, 0, 1, 0, 0, 0, + 6, 4, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 22, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 4, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 5, 0, 0, 0, + 6, 0, 0, 0, 7, 0, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 29, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 31, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 5, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 9, 0, + 0, 0, 10, 0, 0, 0, + 11, 0, 0, 0, 12, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 17, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 9, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 10, + 226, 0, 16, 0, 5, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 14, 0, + 0, 0, 15, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 11, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 23, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 13, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 68, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 21, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 18, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 127, + 0, 0, 0, 0, 192, 31, + 240, 7, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 84, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 10, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 26, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 128, + 63, 0, 0, 0, 0, 224, + 0, 248, 3, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 12, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 88, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 15, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 34, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 96, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, + 7, 0, 0, 0, 8, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 10, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 14, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 50, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 17, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 4, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 9, 0, 0, 0, + 10, 0, 0, 0, 11, 0, + 0, 0, 12, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 18, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 21, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 23, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 25, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 5, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 13, 0, 0, 0, 14, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 27, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 26, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 30, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 20, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 128, 63, 0, 0, 0, 0, + 224, 15, 248, 3, 0, 0, + 0, 0, 254, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 84, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 27, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 9, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 23, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 192, 31, 0, 0, 0, + 0, 240, 0, 252, 1, 0, + 0, 0, 0, 127, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 50, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 4, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 12, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 7, 0, 0, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 20, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 9, 0, + 0, 0, 10, 0, 0, 0, + 11, 0, 0, 0, 12, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 12, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 210, 0, 16, 0, + 1, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 15, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 20, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 60, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 41, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 128, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 11, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 10, + 210, 0, 16, 0, 1, 0, + 0, 0, 6, 9, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 192, 7, 0, + 0, 0, 0, 0, 0, 0, + 192, 7, 0, 124, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 248, 0, + 128, 15, 0, 0, 0, 0, + 0, 248, 0, 128, 15, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 68, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 21, 0, 0, 0, + 41, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 9, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 1, 64, 0, 0, 17, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 31, + 0, 240, 1, 0, 0, 0, + 240, 1, 0, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 26, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 22, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 224, + 0, 0, 62, 0, 224, 3, + 0, 0, 0, 0, 0, 62, + 60, 0, 0, 7, 18, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 146, 0, + 16, 0, 6, 0, 0, 0, + 6, 4, 16, 0, 10, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 124, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 31, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 28, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 84, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 29, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 128, + 30, 0, 0, 7, 66, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 68, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 48, 0, + 0, 1, 79, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 26, 144, 208, 0, + 128, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 3, 0, 4, 3, + 42, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 54, 0, 0, 5, 130, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 48, 0, + 0, 1, 80, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 3, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 168, 0, + 0, 9, 242, 224, 17, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 12, 0, 0, 0, 21, 0, + 0, 1, 62, 0, 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_EncodeBlockCS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_EncodeBlockCS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..13cd16657fd69525b50856c5b093fbe7e4370b69 Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_EncodeBlockCS.pdb differ diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode02CS.inc b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode02CS.inc new file mode 100644 index 0000000000000000000000000000000000000000..5f627d3b004dcadf0c6f23b99dbe30543e7f48e7 --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode02CS.inc @@ -0,0 +1,3823 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.000000, 15, 0, 0}, + { 65981199646559862000000000.000000, 15, 0, 0}, + { 15358528172589056.000000, 15, 0, 0}, + { 3584194248704.000000, 15, 0, 1}, + { -0.000000, 15, 0, 1}, + { -0.000000, 15, 0, 1}, + { 14680365989888.000000, 15, 0, 1}, + { 15362462362632192.000000, 15, 0, 2}, + { -0.000000, 15, 0, 2}, + { -0.000000, 15, 0, 2}, + { -0.000000, 15, 0, 2}, + { -0.000000, 15, 0, 2}, + { -0.000000, 15, 0, 3}, + { -0.000000, 15, 0, 3}, + { -0.000000, 15, 0, 3}, + { 0.000000, 15, 0, 3}, + { -0.000000, 15, 0, 4}, + { 0.000000, 2, 0, 4}, + { -0.000000, 8, 0, 4}, + { 22076467445760.000000, 2, 0, 4}, + { -0.000000, 2, 0, 5}, + { 70798013459086900000000000.000000, 8, 0, 5}, + { -0.000000, 8, 0, 5}, + { 0.000000, 15, 0, 5}, + { 0x0050a4a4, 2, 0, 6}, + { -0.000000, 8, 0, 6}, + { 0.000000, 2, 0, 6}, + { 17610885206241624000000000.000000, 2, 0, 6}, + { -0.000000, 8, 0, 6}, + { -0.000000, 8, 0, 7}, + { 22097854464.000000, 2, 0, 7}, + { 65888818352238725000000000.000000, 2, 0, 7}, + { -0.000000, 15, 0, 7}, + { 19411582976.000000, 15, 0, 8}, + { -0.000000, 6, 0, 8}, + { 0.000000, 8, 0, 8}, + { 0.000000, 2, 0, 8}, + { 0.000000, 8, 0, 9}, + { 0.000000, 15, 0, 9}, + { 22151331840.000000, 15, 0, 9}, + { 9304358912.000000, 2, 0, 9}, + { -0.000000, 8, 0, 10}, + { 271536072765004600000000.000000, 2, 0, 10}, + { -0.000000, 2, 0, 10}, + { 21517107200.000000, 2, 0, 10}, + { 12724757752857623000000000.000000, 15, 0, 10}, + { 1365.320801, 15, 0, 11}, + { 272006464738884190000000.000000, 6, 0, 11}, + { -0.000000, 6, 0, 11}, + { 5783798415360.000000, 2, 0, 11}, + { -0.000000, 6, 0, 12}, + { -0.000000, 8, 0, 12}, + { -0.000000, 15, 0, 12}, + { -0.000000, 15, 0, 12}, + { -0.000000, 2, 0, 13}, + { -0.000000, 2, 0, 13}, + { -0.000000, 15, 0, 13}, + { -0.000000, 15, 0, 13}, + { -0.000000, 15, 0, 14}, + { -0.000000, 15, 0, 14}, + { 4.007874, 15, 0, 14}, + { -0.000000, 2, 0, 14}, + { -0.000000, 2, 0, 15}, + { 0.000000, 15, 0, 15}, + { 0, 3, 15, 0}, + { 4, 3, 8, 0}, + { 9, 15, 8, 0}, + { 13, 15, 3, 0}, + { 17, 8, 15, 0}, + { 21, 3, 15, 1}, + { 26, 15, 3, 1}, + { 30, 15, 8, 1}, + { 34, 8, 15, 1}, + { 38, 8, 15, 1}, + { 43, 6, 15, 1}, + { 47, 6, 15, 1}, + { 51, 6, 15, 1}, + { 55, 5, 15, 1}, + { 60, 3, 15, 2}, + { 64, 3, 8, 2}, + { 0, 3, 15, 2}, + { 9, 3, 8, 2}, + { 18, 8, 15, 2}, + { 27, 15, 3, 2}, + { 37, 3, 15, 2}, + { 46, 3, 8, 2}, + { 55, 6, 15, 2}, + { 64, 10, 8, 3}, + { 0, 5, 3, 3}, + { 0, 8, 15, 3}, + { 0, 8, 6, 3}, + { 0, 6, 10, 3}, + { 0, 8, 15, 3}, + { 0, 5, 15, 3}, + { 0, 15, 10, 3}, + { 0, 15, 8, 3}, + { 0, 8, 15, 3}, + { 21, 15, 3, 4}, + { 43, 3, 15, 4}, + { 64, 5, 10, 4}, + { 0, 6, 10, 4}, + { 0, 10, 8, 4}, + { 0, 8, 9, 4}, + { 0, 15, 10, 4}, + { 0, 15, 6, 4}, + { 0, 3, 15, 4}, + { 0, 15, 8, 5}, + { 0, 5, 15, 5}, + { 0, 15, 3, 5}, + { 0, 15, 6, 5}, + { 0, 15, 6, 5}, + { 0, 15, 8, 5}, + { 0, 3, 15, 5}, + { 0, 15, 3, 5}, + { 0, 5, 15, 5}, + { 0, 5, 15, 6}, + { 0, 5, 15, 6}, + { 0, 8, 15, 6}, + { 0, 5, 15, 6}, + { 0, 10, 15, 6}, + { 0, 5, 15, 6}, + { 0, 10, 15, 6}, + { 0, 8, 15, 6}, + { 0, 13, 15, 6}, + { 0, 15, 3, 7}, + { 0, 12, 15, 7}, + { 0, 3, 15, 7}, + { 0, 3, 8, 7}, + { 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, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_structured t1, 16 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 29 +dcl_indexableTemp x0[12], 4 +dcl_indexableTemp x1[3], 4 +dcl_indexableTemp x2[3], 4 +dcl_indexableTemp x3[3], 4 +dcl_tgsm_structured g0, 100, 64 +dcl_thread_group 64, 1, 1 +iadd r0.x, vThreadGroupID.x, cb0[1].x +ult r1.xyzw, vThreadIDInGroupFlattened.xxxx, l(16, 32, 8, 4) +if_nz r1.x + udiv r0.y, null, r0.x, cb0[0].y + imad r0.z, -r0.y, cb0[0].y, r0.x + ishl r0.z, r0.z, l(2) + ishl r0.y, r0.y, l(2) + and r0.w, vThreadIDInGroupFlattened.x, l(3) + iadd r2.x, r0.w, r0.z + ushr r0.z, vThreadIDInGroupFlattened.x, l(2) + iadd r2.y, r0.z, r0.y + mov r2.zw, l(0,0,0,0) + ld r2.xyzw, r2.xyzw, t0.xyzw + mul r2.xyzw, r2.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000) + ftou r2.xyzw, r2.xyzw + umin r2.xyzw, r2.xyzw, l(255, 255, 255, 255) + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(0), r2.xyzw +endif +sync_g_t +store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), l(-1) +movc r0.y, cb0[0].w, l(64), l(16) +ult r0.y, vThreadIDInGroupFlattened.x, r0.y +if_nz r0.y + iadd r0.y, vThreadIDInGroupFlattened.x, l(64) + mov x0[0].x, l(-1) + mov x0[1].x, l(-1) + mov x0[2].x, l(-1) + mov x0[0].y, l(0) + mov x0[1].y, l(0) + mov x0[2].y, l(0) + mov x0[4].x, l(-1) + mov x0[5].x, l(-1) + mov x0[6].x, l(-1) + mov x0[4].y, l(0) + mov x0[5].y, l(0) + mov x0[6].y, l(0) + mov x0[8].x, l(-1) + mov x0[9].x, l(-1) + mov x0[10].x, l(-1) + mov x0[8].y, l(0) + mov x0[9].y, l(0) + mov x0[10].y, l(0) + iadd r0.z, r0.y, l(-64) + mov r0.w, l(0) + loop + uge r2.x, r0.w, l(16) + breakc_nz r2.x + ld_structured r2.xyz, r0.w, l(0), g0.xyzx + ishl r2.w, r0.w, l(1) + ushr r2.w, icb[r0.z + 0].x, r2.w + and r2.w, r2.w, l(3) + ieq r3.x, r2.w, l(2) + if_nz r3.x + mov r3.x, x0[8].x + mov r3.y, x0[9].x + mov r3.z, x0[10].x + umin r3.xyz, r2.xyzx, r3.xyzx + mov x0[8].x, r3.x + mov x0[9].x, r3.y + mov x0[10].x, r3.z + mov r3.x, x0[8].y + mov r3.y, x0[9].y + mov r3.z, x0[10].y + umax r3.xyz, r2.xyzx, r3.xyzx + mov x0[8].y, r3.x + mov x0[9].y, r3.y + mov x0[10].y, r3.z + else + ieq r2.w, r2.w, l(1) + if_nz r2.w + mov r3.x, x0[4].x + mov r3.y, x0[5].x + mov r3.z, x0[6].x + umin r3.xyz, r2.xyzx, r3.xyzx + mov x0[4].x, r3.x + mov x0[5].x, r3.y + mov x0[6].x, r3.z + mov r3.x, x0[4].y + mov r3.y, x0[5].y + mov r3.z, x0[6].y + umax r3.xyz, r2.xyzx, r3.xyzx + mov x0[4].y, r3.x + mov x0[5].y, r3.y + mov x0[6].y, r3.z + else + mov r3.x, x0[0].x + mov r3.y, x0[1].x + mov r3.z, x0[2].x + umin r3.xyz, r2.xyzx, r3.xyzx + mov x0[0].x, r3.x + mov x0[1].x, r3.y + mov x0[2].x, r3.z + mov r3.x, x0[0].y + mov r3.y, x0[1].y + mov r3.z, x0[2].y + umax r2.xyz, r2.xyzx, r3.xyzx + mov x0[0].y, r2.x + mov x0[1].y, r2.y + mov x0[2].y, r2.z + endif + endif + iadd r0.w, r0.w, l(1) + endloop + mov r2.x, x0[0].x + mov r2.y, x0[1].x + mov r2.z, x0[2].x + mov r3.x, x0[0].y + mov r3.y, x0[1].y + mov r3.z, x0[2].y + mov r4.x, x0[4].x + mov r4.y, x0[5].x + mov r4.z, x0[6].x + mov r5.x, x0[4].y + mov r5.y, x0[5].y + mov r5.z, x0[6].y + mov r6.x, x0[8].x + mov r6.y, x0[9].x + mov r6.z, x0[10].x + mov r7.x, x0[8].y + mov r7.y, x0[9].y + mov r7.z, x0[10].y + movc r0.w, cb0[0].w, l(1), l(64) + iadd r2.xyz, r2.xyzx, l(4, 4, 4, 0) + umin r2.xyz, r2.xyzx, l(255, 255, 255, 0) + ushr r8.xyz, r2.xyzx, l(3) + and r8.xyz, r8.xyzx, l(30, 30, 30, 0) + iadd r3.xyz, r3.xyzx, l(4, 4, 4, 0) + umin r3.xyz, r3.xyzx, l(255, 255, 255, 0) + ushr r9.xyz, r3.xyzx, l(3) + and r9.xyz, r9.xyzx, l(30, 30, 30, 0) + and r10.xyz, r2.xyzx, l(248, 248, 248, 0) + ushr r2.xyz, r2.xyzx, l(5) + iadd r2.xyz, r2.xyzx, r10.xyzx + and r10.xyz, r3.xyzx, l(248, 248, 248, 0) + ushr r3.xyz, r3.xyzx, l(5) + iadd r3.xyz, r3.xyzx, r10.xyzx + iadd r4.xyz, r4.xyzx, l(4, 4, 4, 0) + umin r4.xyz, r4.xyzx, l(255, 255, 255, 0) + ushr r10.xyz, r4.xyzx, l(3) + and r10.xyz, r10.xyzx, l(30, 30, 30, 0) + iadd r5.xyz, r5.xyzx, l(4, 4, 4, 0) + umin r5.xyz, r5.xyzx, l(255, 255, 255, 0) + ushr r11.xyz, r5.xyzx, l(3) + and r11.xyz, r11.xyzx, l(30, 30, 30, 0) + and r12.xyz, r4.xyzx, l(248, 248, 248, 0) + ushr r4.xyz, r4.xyzx, l(5) + iadd r4.xyz, r4.xyzx, r12.xyzx + and r12.xyz, r5.xyzx, l(248, 248, 248, 0) + ushr r5.xyz, r5.xyzx, l(5) + iadd r5.xyz, r5.xyzx, r12.xyzx + iadd r6.xyz, r6.xyzx, l(4, 4, 4, 0) + umin r6.xyz, r6.xyzx, l(255, 255, 255, 0) + ushr r12.xyz, r6.xyzx, l(3) + and r12.xyz, r12.xyzx, l(30, 30, 30, 0) + iadd r7.xyz, r7.xyzx, l(4, 4, 4, 0) + umin r7.xyz, r7.xyzx, l(255, 255, 255, 0) + ushr r13.xyz, r7.xyzx, l(3) + and r13.xyz, r13.xyzx, l(30, 30, 30, 0) + and r14.xyz, r6.xyzx, l(248, 248, 248, 0) + ushr r6.xyz, r6.xyzx, l(5) + iadd r6.xyz, r6.xyzx, r14.xyzx + and r14.xyz, r7.xyzx, l(248, 248, 248, 0) + ushr r7.xyz, r7.xyzx, l(5) + iadd r7.xyz, r7.xyzx, r14.xyzx + mov r2.w, r3.z + mov r3.w, r2.y + mov r4.w, r5.z + mov r5.w, r4.y + mov r6.w, r7.z + mov r7.w, r6.y + mov r14.y, l(255) + mov r2.y, cb0[0].w + mov r15.xy, l(0,-1,0,0) + mov r16.x, l(0) + loop + uge r3.z, r16.x, r0.w + breakc_nz r3.z + ieq r3.z, r2.y, l(2) + if_z r2.y + ushr r16.y, r16.x, l(1) + and r14.zw, r16.xxxy, l(0, 0, 1, 1) + iadd r17.xyz, r8.xyzx, r14.zzzz + ishl r17.xyz, r17.xyzx, l(3) + ushr r18.xyz, r17.xyzx, l(5) + iadd r17.xzw, r17.zzxy, r18.zzxy + iadd r18.xyz, r9.xyzx, r14.wwww + ishl r18.xyz, r18.xyzx, l(3) + ushr r19.xyz, r18.xyzx, l(5) + iadd r18.xyz, r18.yxzy, r19.yxzy + mov r17.y, r18.z + mov r18.w, r17.w + mov r14.zw, r18.wwwx + mov r18.x, r17.z + else + mov r17.xy, r2.zwzz + mov r14.zw, r3.wwwy + mov r18.x, r2.x + mov r18.y, r3.x + endif + mov x0[3].xy, l(255,255,0,0) + mov x0[2].xy, r17.xyxx + mov x0[1].xy, r14.zwzz + mov x0[0].xy, r18.xyxx + if_z r2.y + ushr r19.x, r16.x, l(2) + ushr r19.y, r16.x, l(3) + and r15.zw, r19.xxxy, l(0, 0, 1, 1) + iadd r19.xyz, r10.xyzx, r15.zzzz + ishl r19.xyz, r19.xyzx, l(3) + ushr r20.xyz, r19.xyzx, l(5) + iadd r19.xzw, r19.zzxy, r20.zzxy + iadd r20.xyz, r11.xyzx, r15.wwww + ishl r20.xyz, r20.xyzx, l(3) + ushr r21.xyz, r20.xyzx, l(5) + iadd r20.xyz, r20.yxzy, r21.yxzy + mov r19.y, r20.z + mov r20.w, r19.w + mov r15.zw, r20.wwwx + mov r20.x, r19.z + else + mov r19.xy, r4.zwzz + mov r15.zw, r5.wwwy + mov r20.x, r4.x + mov r20.y, r5.x + endif + mov x0[7].xy, l(255,255,0,0) + mov x0[6].xy, r19.xyxx + mov x0[5].xy, r15.zwzz + mov x0[4].xy, r20.xyxx + if_z r2.y + ushr r21.x, r16.x, l(4) + ushr r21.y, r16.x, l(5) + and r16.zw, r21.xxxy, l(0, 0, 1, 1) + iadd r21.xyz, r12.xyzx, r16.zzzz + ishl r21.xyz, r21.xyzx, l(3) + ushr r22.xyz, r21.xyzx, l(5) + iadd r21.xzw, r21.zzxy, r22.zzxy + iadd r22.xyz, r13.xyzx, r16.wwww + ishl r22.xyz, r22.xyzx, l(3) + ushr r23.xyz, r22.xyzx, l(5) + iadd r22.xyz, r22.yxzy, r23.yxzy + mov r21.y, r22.z + mov r22.w, r21.w + mov r16.zw, r22.wwwx + mov r22.x, r21.z + else + mov r21.xy, r6.zwzz + mov r16.zw, r7.wwwy + mov r22.x, r6.x + mov r22.y, r7.x + endif + mov x0[11].xy, l(255,255,0,0) + mov x0[10].xy, r21.xyxx + mov x0[9].xy, r16.zwzz + mov x0[8].xy, r22.xyxx + ineg r23.x, r18.x + ineg r23.y, r14.z + ineg r23.z, r17.x + mov r18.z, r14.w + mov r18.w, r17.y + iadd r17.xyz, r18.yzwy, r23.xyzx + mov x1[0].xyz, r17.xyzx + ineg r18.x, r20.x + ineg r18.y, r15.z + ineg r18.z, r19.x + mov r20.z, r15.w + mov r20.w, r19.y + iadd r18.xyz, r18.xyzx, r20.yzwy + mov x1[1].xyz, r18.xyzx + ineg r19.x, r22.x + ineg r19.y, r16.z + ineg r19.z, r21.x + mov r22.z, r16.w + mov r22.w, r21.y + iadd r19.xyz, r19.xyzx, r22.yzwy + mov x1[2].xyz, r19.xyzx + mov x1[2].w, l(0) + mov x1[1].w, l(0) + mov x1[0].w, l(0) + imul null, r14.zw, r17.xxxy, r17.xxxy + iadd r4.y, r14.w, r14.z + imad r4.y, r17.z, r17.z, r4.y + mov x2[0].x, r4.y + imul null, r14.zw, r18.xxxy, r18.xxxy + iadd r5.z, r14.w, r14.z + imad r5.z, r18.z, r18.z, r5.z + mov x2[1].x, r5.z + imul null, r14.zw, r19.xxxy, r19.xxxy + iadd r6.y, r14.w, r14.z + imad r6.y, r19.z, r19.z, r6.y + mov x2[2].x, r6.y + mov x3[0].x, l(0) + mov x3[1].x, icb[r0.y + 0].y + mov x3[2].x, icb[r0.y + 0].z + mov r7.z, l(0) + loop + uge r8.w, r7.z, l(3) + breakc_nz r8.w + mov r17.xyzw, x1[r7.z + 0].xyzw + mov r8.w, x3[r7.z + 0].x + ld_structured r18.xyzw, r8.w, l(0), g0.xyzw + ishl r8.w, r7.z, l(2) + mov r9.w, x0[r8.w + 0].x + mov r10.w, x0[r8.w + 1].x + mov r11.w, x0[r8.w + 2].x + mov r12.w, x0[r8.w + 3].x + ineg r19.x, r9.w + ineg r19.y, r10.w + ineg r19.z, r11.w + ineg r19.w, r12.w + iadd r18.xyzw, r18.xyzw, r19.xyzw + imul null, r14.zw, r17.xxxy, r18.xxxy + iadd r13.w, r14.w, r14.z + imad r13.w, r17.z, r18.z, r13.w + imad r13.w, r17.w, r18.w, r13.w + mov r14.z, x2[r7.z + 0].x + ilt r14.w, l(0), r14.z + ilt r15.z, l(0), r13.w + and r14.w, r14.w, r15.z + itof r13.w, r13.w + mul r13.w, r13.w, l(63.499989) + ftou r13.w, r13.w + ishl r14.z, r14.z, l(5) + ult r13.w, r14.z, r13.w + and r13.w, r13.w, r14.w + if_nz r13.w + ineg r17.xyzw, r17.xyzw + mov x1[r7.z + 0].xyzw, r17.xyzw + mov r13.w, x0[r8.w + 0].y + mov r14.z, x0[r8.w + 1].y + mov r14.w, x0[r8.w + 2].y + mov r15.z, x0[r8.w + 3].y + mov x0[r8.w + 0].x, r13.w + mov x0[r8.w + 1].x, r14.z + mov x0[r8.w + 2].x, r14.w + mov x0[r8.w + 3].x, r15.z + mov x0[r8.w + 0].y, r9.w + mov x0[r8.w + 1].y, r10.w + mov x0[r8.w + 2].y, r11.w + mov x0[r8.w + 3].y, r12.w + endif + iadd r7.z, r7.z, l(1) + endloop + mov r17.xyzw, x1[2].xyzw + mov r7.z, x0[8].x + mov r8.w, x0[9].x + mov r9.w, x0[10].x + mov r10.w, x0[11].x + ineg r18.x, r7.z + ineg r18.y, r8.w + ineg r18.z, r9.w + ineg r18.w, r10.w + ige r11.w, l(0), r6.y + itof r12.w, r6.y + movc r19.xyz, r3.zzzz, l(128,3,32,0), l(64,7,16,0) + mov r20.xyzw, x1[1].xyzw + mov r3.z, x0[4].x + mov r13.w, x0[5].x + mov r14.z, x0[6].x + mov r14.w, x0[7].x + ineg r21.x, r3.z + ineg r21.y, r13.w + ineg r21.zw, r14.zzzw + ige r15.z, l(0), r5.z + itof r15.w, r5.z + mov r22.xyzw, x1[0].xyzw + mov r16.z, x0[0].x + mov r16.w, x0[1].x + mov r19.w, x0[2].x + mov r23.x, x0[3].x + ineg r24.xy, r16.zwzz + ineg r24.z, r19.w + ineg r24.w, r23.x + ige r23.y, l(0), r4.y + itof r23.z, r4.y + mov r23.w, l(0) + mov r16.y, l(0) + loop + uge r25.x, r23.w, l(16) + breakc_nz r25.x + ishl r25.x, r23.w, l(1) + ushr r25.x, icb[r0.z + 0].x, r25.x + and r25.x, r25.x, l(3) + ieq r25.y, r25.x, l(2) + if_nz r25.y + ld_structured r26.xyzw, r23.w, l(0), g0.xyzw + iadd r26.xyzw, r18.xyzw, r26.xyzw + imul null, r25.yz, r17.xxyx, r26.xxyx + iadd r25.y, r25.z, r25.y + imad r25.y, r17.z, r26.z, r25.y + imad r25.y, r17.w, r26.w, r25.y + ige r25.z, l(0), r25.y + or r25.z, r11.w, r25.z + ilt r25.w, r25.y, r6.y + itof r25.y, r25.y + mul r25.y, r25.y, l(63.499989) + div r25.y, r25.y, r12.w + ftou r25.y, r25.y + iadd r25.y, r19.x, r25.y + movc r25.y, r25.w, icb[r25.y + 0].w, r19.y + movc r25.y, r25.z, l(0), r25.y + else + ieq r25.z, r25.x, l(1) + if_nz r25.z + ld_structured r26.xyzw, r23.w, l(0), g0.xyzw + iadd r26.xyzw, r21.xyzw, r26.xyzw + imul null, r25.zw, r20.xxxy, r26.xxxy + iadd r25.z, r25.w, r25.z + imad r25.z, r20.z, r26.z, r25.z + imad r25.z, r20.w, r26.w, r25.z + ige r25.w, l(0), r25.z + or r25.w, r15.z, r25.w + ilt r26.x, r25.z, r5.z + itof r25.z, r25.z + mul r25.z, r25.z, l(63.499989) + div r25.z, r25.z, r15.w + ftou r25.z, r25.z + iadd r25.z, r19.x, r25.z + movc r25.z, r26.x, icb[r25.z + 0].w, r19.y + movc r25.y, r25.w, l(0), r25.z + else + ld_structured r26.xyzw, r23.w, l(0), g0.xyzw + iadd r26.xyzw, r24.xyzw, r26.xyzw + imul null, r25.zw, r22.xxxy, r26.xxxy + iadd r25.z, r25.w, r25.z + imad r25.z, r22.z, r26.z, r25.z + imad r25.z, r22.w, r26.w, r25.z + ige r25.w, l(0), r25.z + or r25.w, r23.y, r25.w + ilt r26.x, r25.z, r4.y + itof r25.z, r25.z + mul r25.z, r25.z, l(63.499989) + div r25.z, r25.z, r23.z + ftou r25.z, r25.z + iadd r25.z, r19.x, r25.z + movc r25.z, r26.x, icb[r25.z + 0].w, r19.y + movc r25.y, r25.w, l(0), r25.z + endif + endif + iadd r25.y, r19.z, r25.y + iadd r25.z, l(64), -icb[r25.y + 64].x + ishl r25.x, r25.x, l(2) + mov r26.x, x0[r25.x + 0].x + mov r26.y, x0[r25.x + 1].x + mov r26.z, x0[r25.x + 2].x + mov r27.x, x0[r25.x + 0].y + mov r27.y, x0[r25.x + 1].y + mov r27.z, x0[r25.x + 2].y + imul null, r25.xyw, r27.xyxz, icb[r25.y + 64].xxxx + imad r25.xyz, r25.zzzz, r26.xyzx, r25.xywx + iadd r25.xyz, r25.xyzx, l(32, 32, 32, 0) + ushr r25.xyw, r25.xyxz, l(6) + ld_structured r26.xyzw, r23.w, l(0), g0.xyzw + ult r27.xyz, r25.xywx, r26.xyzx + mov r25.z, r26.x + movc r27.xw, r27.xxxx, r25.zzzx, r25.xxxz + mov r25.xz, r26.yyzy + movc r25.xyzw, r27.yyzz, r25.xyzw, r25.yxwz + ult r26.x, l(255), r26.w + mov r14.x, r26.w + movc r26.xw, r26.xxxx, r14.yyyx, r14.xxxy + ineg r28.x, r27.w + ineg r28.yz, r25.yywy + ineg r28.w, r26.x + mov r26.x, r27.x + mov r26.yz, r25.xxzx + iadd r25.xyzw, r28.xyzw, r26.xyzw + imul null, r25.xy, r25.xyxx, r25.xyxx + iadd r14.x, r25.y, r25.x + imad r14.x, r25.z, r25.z, r14.x + utof r14.x, r14.x + utof r25.x, r25.w + mul r25.x, r25.x, r25.x + mad r14.x, r25.x, cb0[1].z, r14.x + ftou r14.x, r14.x + iadd r16.y, r14.x, r16.y + iadd r23.w, r23.w, l(1) + endloop + ult r3.z, r16.y, r15.y + movc r15.xy, r3.zzzz, r16.xyxx, r15.xyxx + iadd r16.x, r16.x, l(1) + endloop + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r15.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r15.x +endif +sync_g_t +if_nz r1.y + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(32) + ld_structured r3.x, r0.y, l(16), g0.xxxx + ld_structured r4.x, r0.y, l(24), g0.xxxx + ld_structured r5.x, r0.y, l(32), g0.xxxx + ult r0.y, r3.x, r2.x + if_nz r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r3.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r4.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r5.x + endif +endif +if_nz r1.x + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(16) + ld_structured r3.x, r0.y, l(16), g0.xxxx + ld_structured r4.x, r0.y, l(24), g0.xxxx + ld_structured r5.x, r0.y, l(32), g0.xxxx + ult r0.y, r3.x, r2.x + if_nz r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r3.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r4.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r5.x + endif +endif +if_nz r1.z + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(8) + ld_structured r3.x, r0.y, l(16), g0.xxxx + ld_structured r4.x, r0.y, l(24), g0.xxxx + ld_structured r5.x, r0.y, l(32), g0.xxxx + ult r0.y, r3.x, r2.x + if_nz r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r3.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r4.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r5.x + endif +endif +if_nz r1.w + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(4) + ld_structured r2.x, r0.y, l(16), g0.xxxx + ld_structured r3.x, r0.y, l(24), g0.xxxx + ld_structured r4.x, r0.y, l(32), g0.xxxx + ult r0.y, r2.x, r1.x + if_nz r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r2.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r3.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r4.x + endif +endif +ult r0.yz, vThreadIDInGroupFlattened.xxxx, l(0, 2, 1, 0) +if_nz r0.y + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(2) + ld_structured r2.x, r0.y, l(16), g0.xxxx + ld_structured r3.x, r0.y, l(24), g0.xxxx + ld_structured r4.x, r0.y, l(32), g0.xxxx + ult r0.y, r2.x, r1.x + if_nz r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r2.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r3.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r4.x + endif +endif +if_nz r0.z + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(1) + ld_structured r2.x, r0.y, l(16), g0.xxxx + ld_structured r3.x, r0.y, l(24), g0.xxxx + ld_structured r4.x, r0.y, l(32), g0.xxxx + ult r0.y, r2.x, r1.x + if_nz r0.y + store_structured g0.x, vThreadIDInGroupFlattened.x, l(16), r2.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(24), r3.x + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r4.x + endif + ld_structured r1.x, r0.x, l(0), t1.xxxx + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + ult r0.y, r2.x, r1.x + if_nz r0.y + ld_structured r2.z, vThreadIDInGroupFlattened.x, l(24), g0.xxxx + ld_structured r2.w, vThreadIDInGroupFlattened.x, l(32), g0.xxxx + mov r2.y, cb0[0].w + else + ld_structured r2.xyzw, r0.x, l(0), t1.xyzw + endif + store_structured u0.xyzw, r0.x, l(0), r2.xyzw +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC7Encode_TryMode02CS[] = +{ + 68, 88, 66, 67, 122, 4, + 188, 46, 162, 127, 38, 170, + 88, 175, 162, 101, 250, 119, + 32, 234, 1, 0, 0, 0, + 172, 70, 0, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 88, 70, 0, 0, + 64, 0, 5, 0, 150, 17, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 2, 3, + 0, 0, 80, 80, 104, 170, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 64, 80, 90, 106, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 66, + 90, 90, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 160, 80, 84, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 165, 165, 15, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 80, 80, + 160, 160, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 160, 160, 85, 85, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 80, 80, 90, 90, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 85, 170, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 85, 85, 170, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 85, 170, 170, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 144, 144, + 144, 144, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 148, 148, 148, 148, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 164, 164, 164, 164, 15, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 80, 148, + 165, 169, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 80, 66, 10, 42, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 64, 80, 148, 165, 15, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 84, 80, + 66, 10, 2, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 165, 165, 165, + 8, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 160, 160, 160, 85, 2, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 84, 84, + 168, 168, 2, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 64, 64, 106, 106, + 8, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 80, 164, 164, 8, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 5, + 26, 26, 15, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 164, 164, 80, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 144, 144, 165, 170, 8, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 20, 105, + 105, 20, 2, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 20, 105, 105, + 2, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 160, 133, 133, 160, 8, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 20, 20, + 130, 170, 8, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 80, 164, 164, 80, + 2, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 0, 2, 90, 106, 2, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 128, + 165, 169, 15, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 168, 160, 144, 80, + 15, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 80, 144, 160, 168, 6, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 36, 36, + 36, 36, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 85, 170, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 36, 73, 146, 36, 8, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 36, 146, + 73, 36, 15, 0, 0, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 80, 10, 165, 80, + 15, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 80, 165, 10, 80, 2, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 68, 68, + 170, 170, 8, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 102, 102, + 2, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 160, 165, 160, 165, 2, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 160, 80, + 160, 80, 2, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 40, 105, 40, 105, + 15, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 68, 170, 170, 68, 15, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 102, + 102, 102, 6, 0, 0, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 68, 68, 68, 170, + 6, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 168, 84, 168, 84, 2, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 128, 149, + 128, 149, 6, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 150, 150, 150, + 8, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 168, 84, 84, 168, 15, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 128, 149, + 149, 128, 15, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 20, 20, 20, 170, + 2, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 0, 0, 150, 150, 2, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 20, 20, + 170, 170, 15, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 160, 80, 80, 160, + 15, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 160, 165, 165, 160, 15, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, + 0, 150, 15, 0, 0, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 128, 64, 128, 64, + 15, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 168, 169, 168, 169, 2, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 68, 170, + 170, 170, 2, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 84, 82, 74, 42, + 15, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 15, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 0, 15, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 34, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 38, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 0, 43, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 0, 47, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 51, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 0, 60, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 64, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 2, 0, + 0, 0, 9, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 18, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 2, 0, 0, 0, 27, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 37, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 46, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 55, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 2, 0, + 0, 0, 64, 0, 0, 0, + 10, 0, 0, 0, 8, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 6, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 10, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 10, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 8, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 21, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 4, 0, 0, 0, 43, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 4, 0, + 0, 0, 64, 0, 0, 0, + 5, 0, 0, 0, 10, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 10, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 9, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 10, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 8, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 8, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 15, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 7, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 162, 0, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 0, 158, 0, 0, 4, + 0, 224, 17, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 95, 0, 0, 2, 0, 64, + 2, 0, 95, 0, 0, 2, + 18, 16, 2, 0, 104, 0, + 0, 2, 29, 0, 0, 0, + 105, 0, 0, 4, 0, 0, + 0, 0, 12, 0, 0, 0, + 4, 0, 0, 0, 105, 0, + 0, 4, 1, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 105, 0, 0, 4, + 2, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 105, 0, 0, 4, 3, 0, + 0, 0, 3, 0, 0, 0, + 4, 0, 0, 0, 160, 0, + 0, 5, 0, 240, 17, 0, + 0, 0, 0, 0, 100, 0, + 0, 0, 64, 0, 0, 0, + 155, 0, 0, 4, 64, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 16, + 2, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 79, 0, 0, 9, + 242, 0, 16, 0, 1, 0, + 0, 0, 6, 64, 2, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 78, 0, 0, 9, + 34, 0, 16, 0, 0, 0, + 0, 0, 0, 208, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 11, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 6, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 7, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 127, 67, 0, 0, 127, 67, + 28, 0, 0, 5, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 84, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 55, 0, 0, 10, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 79, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 192, 255, + 255, 255, 54, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 80, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 3, 0, 4, 3, 10, 0, + 16, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 242, + 17, 0, 0, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 8, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 144, + 144, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 32, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 3, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 3, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 84, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 83, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 84, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 3, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 83, 0, + 0, 7, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 6, 18, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 84, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 3, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 83, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 54, 0, 0, 6, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 6, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 6, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 7, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 7, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 7, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 55, 0, 0, 10, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 0, + 30, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 84, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 30, 0, 0, 0, + 30, 0, 0, 0, 30, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 2, 64, 0, 0, + 30, 0, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 0, + 30, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 12, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 84, 0, 0, 10, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 30, 0, 0, 0, + 30, 0, 0, 0, 30, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 30, 0, 0, 0, 30, 0, + 0, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 14, 0, 0, 0, 1, 64, + 0, 0, 255, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 2, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 50, 0, + 16, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 16, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 80, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 16, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 3, 0, 4, 3, 42, 0, + 16, 0, 3, 0, 0, 0, + 32, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 31, 0, + 0, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 34, 0, 16, 0, + 16, 0, 0, 0, 10, 0, + 16, 0, 16, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 14, 0, + 0, 0, 6, 4, 16, 0, + 16, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 166, 10, 16, 0, + 14, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 17, 0, 0, 0, 70, 2, + 16, 0, 17, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 17, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 210, 0, + 16, 0, 17, 0, 0, 0, + 166, 4, 16, 0, 17, 0, + 0, 0, 166, 4, 16, 0, + 18, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 246, 15, 16, 0, 14, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 18, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 18, 0, 0, 0, 22, 6, + 16, 0, 18, 0, 0, 0, + 22, 6, 16, 0, 19, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 17, 0, + 0, 0, 42, 0, 16, 0, + 18, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 17, 0, 0, 0, + 54, 0, 0, 5, 194, 0, + 16, 0, 14, 0, 0, 0, + 246, 3, 16, 0, 18, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 18, 0, + 0, 0, 42, 0, 16, 0, + 17, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 50, 0, 16, 0, 17, 0, + 0, 0, 230, 10, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 5, 194, 0, 16, 0, + 14, 0, 0, 0, 246, 7, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 18, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 18, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 54, 0, 0, 9, + 50, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 50, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 17, 0, + 0, 0, 54, 0, 0, 6, + 50, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 14, 0, + 0, 0, 54, 0, 0, 6, + 50, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 18, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 19, 0, + 0, 0, 10, 0, 16, 0, + 16, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 34, 0, + 16, 0, 19, 0, 0, 0, + 10, 0, 16, 0, 16, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 15, 0, 0, 0, 6, 4, + 16, 0, 19, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 166, 10, + 16, 0, 15, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 210, 0, 16, 0, 19, 0, + 0, 0, 166, 4, 16, 0, + 19, 0, 0, 0, 166, 4, + 16, 0, 20, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 246, 15, 16, 0, + 15, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 22, 6, 16, 0, 20, 0, + 0, 0, 22, 6, 16, 0, + 21, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 19, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 19, 0, + 0, 0, 54, 0, 0, 5, + 194, 0, 16, 0, 15, 0, + 0, 0, 246, 3, 16, 0, + 20, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 19, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 50, 0, 16, 0, + 19, 0, 0, 0, 230, 10, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 5, 194, 0, + 16, 0, 15, 0, 0, 0, + 246, 7, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 20, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 20, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 54, 0, + 0, 9, 50, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 50, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 19, 0, 0, 0, 54, 0, + 0, 6, 50, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 230, 10, 16, 0, + 15, 0, 0, 0, 54, 0, + 0, 6, 50, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 20, 0, 0, 0, 31, 0, + 0, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 18, 0, 16, 0, + 21, 0, 0, 0, 10, 0, + 16, 0, 16, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 21, 0, + 0, 0, 10, 0, 16, 0, + 16, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 16, 0, 0, 0, + 6, 4, 16, 0, 21, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 166, 10, 16, 0, 16, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 21, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 22, 0, 0, 0, + 70, 2, 16, 0, 21, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 210, 0, 16, 0, + 21, 0, 0, 0, 166, 4, + 16, 0, 21, 0, 0, 0, + 166, 4, 16, 0, 22, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 22, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 246, 15, + 16, 0, 16, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 22, 0, 0, 0, + 70, 2, 16, 0, 22, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 23, 0, 0, 0, 70, 2, + 16, 0, 22, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 22, 0, + 0, 0, 22, 6, 16, 0, + 22, 0, 0, 0, 22, 6, + 16, 0, 23, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 21, 0, 0, 0, + 42, 0, 16, 0, 22, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 22, 0, + 0, 0, 58, 0, 16, 0, + 21, 0, 0, 0, 54, 0, + 0, 5, 194, 0, 16, 0, + 16, 0, 0, 0, 246, 3, + 16, 0, 22, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 22, 0, 0, 0, + 42, 0, 16, 0, 21, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 50, 0, + 16, 0, 21, 0, 0, 0, + 230, 10, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 5, + 194, 0, 16, 0, 16, 0, + 0, 0, 246, 7, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 22, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 22, 0, 0, 0, + 10, 0, 16, 0, 7, 0, + 0, 0, 21, 0, 0, 1, + 54, 0, 0, 9, 50, 48, + 32, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 50, 48, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 70, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 50, 48, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 230, 10, + 16, 0, 16, 0, 0, 0, + 54, 0, 0, 6, 50, 48, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 70, 0, + 16, 0, 22, 0, 0, 0, + 40, 0, 0, 5, 18, 0, + 16, 0, 23, 0, 0, 0, + 10, 0, 16, 0, 18, 0, + 0, 0, 40, 0, 0, 5, + 34, 0, 16, 0, 23, 0, + 0, 0, 42, 0, 16, 0, + 14, 0, 0, 0, 40, 0, + 0, 5, 66, 0, 16, 0, + 23, 0, 0, 0, 10, 0, + 16, 0, 17, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 18, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 18, 0, + 0, 0, 26, 0, 16, 0, + 17, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 17, 0, 0, 0, 150, 7, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 23, 0, + 0, 0, 54, 0, 0, 6, + 114, 48, 32, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 40, 0, 0, 5, + 18, 0, 16, 0, 18, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 40, 0, + 0, 5, 34, 0, 16, 0, + 18, 0, 0, 0, 42, 0, + 16, 0, 15, 0, 0, 0, + 40, 0, 0, 5, 66, 0, + 16, 0, 18, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 15, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 20, 0, 0, 0, 26, 0, + 16, 0, 19, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 18, 0, 0, 0, + 70, 2, 16, 0, 18, 0, + 0, 0, 150, 7, 16, 0, + 20, 0, 0, 0, 54, 0, + 0, 6, 114, 48, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 40, 0, + 0, 5, 18, 0, 16, 0, + 19, 0, 0, 0, 10, 0, + 16, 0, 22, 0, 0, 0, + 40, 0, 0, 5, 34, 0, + 16, 0, 19, 0, 0, 0, + 42, 0, 16, 0, 16, 0, + 0, 0, 40, 0, 0, 5, + 66, 0, 16, 0, 19, 0, + 0, 0, 10, 0, 16, 0, + 21, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 22, 0, 0, 0, 58, 0, + 16, 0, 16, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 22, 0, 0, 0, + 26, 0, 16, 0, 21, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 19, 0, 0, 0, 150, 7, + 16, 0, 22, 0, 0, 0, + 54, 0, 0, 6, 114, 48, + 32, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 54, 0, 0, 6, 130, 48, + 32, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 130, 48, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 130, 48, + 32, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 194, 0, 16, 0, + 14, 0, 0, 0, 6, 4, + 16, 0, 17, 0, 0, 0, + 6, 4, 16, 0, 17, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 14, 0, 0, 0, + 35, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 17, 0, + 0, 0, 42, 0, 16, 0, + 17, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 194, 0, 16, 0, + 14, 0, 0, 0, 6, 4, + 16, 0, 18, 0, 0, 0, + 6, 4, 16, 0, 18, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 14, 0, 0, 0, + 35, 0, 0, 9, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 18, 0, + 0, 0, 42, 0, 16, 0, + 18, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 194, 0, 16, 0, + 14, 0, 0, 0, 6, 4, + 16, 0, 19, 0, 0, 0, + 6, 4, 16, 0, 19, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 14, 0, 0, 0, + 35, 0, 0, 9, 34, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 19, 0, + 0, 0, 42, 0, 16, 0, + 19, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 7, 18, 48, + 32, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 26, 144, + 144, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 7, 18, 48, 32, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 42, 144, 144, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 80, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 3, 0, 4, 3, 58, 0, + 16, 0, 8, 0, 0, 0, + 54, 0, 0, 7, 242, 0, + 16, 0, 17, 0, 0, 0, + 70, 62, 32, 4, 1, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 10, 48, + 32, 4, 3, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 10, 48, 32, 4, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 8, 130, 0, 16, 0, + 10, 0, 0, 0, 10, 48, + 32, 6, 0, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 54, 0, 0, 8, 130, 0, + 16, 0, 11, 0, 0, 0, + 10, 48, 32, 6, 0, 0, + 0, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 8, + 130, 0, 16, 0, 12, 0, + 0, 0, 10, 48, 32, 6, + 0, 0, 0, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 40, 0, + 0, 5, 18, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 40, 0, 0, 5, 34, 0, + 16, 0, 19, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 40, 0, 0, 5, + 66, 0, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 40, 0, + 0, 5, 130, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 18, 0, 0, 0, + 70, 14, 16, 0, 18, 0, + 0, 0, 70, 14, 16, 0, + 19, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 194, 0, 16, 0, 14, 0, + 0, 0, 6, 4, 16, 0, + 17, 0, 0, 0, 6, 4, + 16, 0, 18, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 42, 0, 16, 0, + 14, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 13, 0, 0, 0, 42, 0, + 16, 0, 17, 0, 0, 0, + 42, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 17, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 54, 0, + 0, 7, 66, 0, 16, 0, + 14, 0, 0, 0, 10, 48, + 32, 4, 2, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 34, 0, 0, 7, + 130, 0, 16, 0, 14, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 14, 0, 0, 0, + 34, 0, 0, 7, 66, 0, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 15, 0, + 0, 0, 43, 0, 0, 5, + 130, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 28, 0, 0, 5, + 130, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 14, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 13, 0, + 0, 0, 42, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 31, 0, + 4, 3, 58, 0, 16, 0, + 13, 0, 0, 0, 40, 0, + 0, 5, 242, 0, 16, 0, + 17, 0, 0, 0, 70, 14, + 16, 0, 17, 0, 0, 0, + 54, 0, 0, 7, 242, 48, + 32, 4, 1, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 17, 0, 0, 0, 54, 0, + 0, 7, 130, 0, 16, 0, + 13, 0, 0, 0, 26, 48, + 32, 4, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 8, + 66, 0, 16, 0, 14, 0, + 0, 0, 26, 48, 32, 6, + 0, 0, 0, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 8, 130, 0, 16, 0, + 14, 0, 0, 0, 26, 48, + 32, 6, 0, 0, 0, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 54, 0, 0, 8, 66, 0, + 16, 0, 15, 0, 0, 0, + 26, 48, 32, 6, 0, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 7, + 18, 48, 32, 4, 0, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 54, 0, 0, 8, 18, 48, + 32, 6, 0, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 14, 0, + 0, 0, 54, 0, 0, 8, + 18, 48, 32, 6, 0, 0, + 0, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 54, 0, + 0, 8, 18, 48, 32, 6, + 0, 0, 0, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 42, 0, + 16, 0, 15, 0, 0, 0, + 54, 0, 0, 7, 34, 48, + 32, 4, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 54, 0, + 0, 8, 34, 48, 32, 6, + 0, 0, 0, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 54, 0, 0, 8, 34, 48, + 32, 6, 0, 0, 0, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 54, 0, 0, 8, + 34, 48, 32, 6, 0, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 21, 0, + 0, 1, 30, 0, 0, 7, + 66, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 54, 0, + 0, 6, 242, 0, 16, 0, + 17, 0, 0, 0, 70, 62, + 32, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 7, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 8, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 9, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 10, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 40, 0, + 0, 5, 18, 0, 16, 0, + 18, 0, 0, 0, 42, 0, + 16, 0, 7, 0, 0, 0, + 40, 0, 0, 5, 34, 0, + 16, 0, 18, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 40, 0, 0, 5, + 66, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 40, 0, + 0, 5, 130, 0, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 33, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 43, 0, + 0, 5, 130, 0, 16, 0, + 12, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 55, 0, 0, 15, 114, 0, + 16, 0, 19, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 128, 0, 0, 0, 3, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 64, 0, 0, 0, + 7, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 242, 0, + 16, 0, 20, 0, 0, 0, + 70, 62, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 13, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 14, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 14, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 40, 0, 0, 5, 18, 0, + 16, 0, 21, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 40, 0, 0, 5, + 34, 0, 16, 0, 21, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 40, 0, + 0, 5, 194, 0, 16, 0, + 21, 0, 0, 0, 166, 14, + 16, 0, 14, 0, 0, 0, + 33, 0, 0, 7, 66, 0, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 43, 0, + 0, 5, 130, 0, 16, 0, + 15, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 242, 0, + 16, 0, 22, 0, 0, 0, + 70, 62, 32, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 16, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 16, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 19, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 23, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 40, 0, 0, 5, 50, 0, + 16, 0, 24, 0, 0, 0, + 230, 10, 16, 0, 16, 0, + 0, 0, 40, 0, 0, 5, + 66, 0, 16, 0, 24, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 40, 0, + 0, 5, 130, 0, 16, 0, + 24, 0, 0, 0, 10, 0, + 16, 0, 23, 0, 0, 0, + 33, 0, 0, 7, 34, 0, + 16, 0, 23, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 43, 0, + 0, 5, 66, 0, 16, 0, + 23, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 23, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 16, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 1, 80, 0, 0, 7, + 18, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 3, 0, 4, 3, 10, 0, + 16, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 25, 0, 0, 0, + 58, 0, 16, 0, 23, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 8, 18, 0, 16, 0, + 25, 0, 0, 0, 10, 144, + 144, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 25, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 25, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 32, 0, + 0, 7, 34, 0, 16, 0, + 25, 0, 0, 0, 10, 0, + 16, 0, 25, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 25, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 26, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 242, 0, 16, 0, 26, 0, + 0, 0, 70, 14, 16, 0, + 18, 0, 0, 0, 70, 14, + 16, 0, 26, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 98, 0, 16, 0, + 25, 0, 0, 0, 6, 1, + 16, 0, 17, 0, 0, 0, + 6, 1, 16, 0, 26, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 35, 0, 0, 9, 34, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 17, 0, + 0, 0, 42, 0, 16, 0, + 26, 0, 0, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 35, 0, 0, 9, 34, 0, + 16, 0, 25, 0, 0, 0, + 58, 0, 16, 0, 17, 0, + 0, 0, 58, 0, 16, 0, + 26, 0, 0, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 33, 0, 0, 7, 66, 0, + 16, 0, 25, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 25, 0, 0, 0, 60, 0, + 0, 7, 66, 0, 16, 0, + 25, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 34, 0, 0, 7, + 130, 0, 16, 0, 25, 0, + 0, 0, 26, 0, 16, 0, + 25, 0, 0, 0, 26, 0, + 16, 0, 6, 0, 0, 0, + 43, 0, 0, 5, 34, 0, + 16, 0, 25, 0, 0, 0, + 26, 0, 16, 0, 25, 0, + 0, 0, 56, 0, 0, 7, + 34, 0, 16, 0, 25, 0, + 0, 0, 26, 0, 16, 0, + 25, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 34, 0, + 16, 0, 25, 0, 0, 0, + 26, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 28, 0, + 0, 5, 34, 0, 16, 0, + 25, 0, 0, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 26, 0, 16, 0, + 25, 0, 0, 0, 55, 0, + 0, 10, 34, 0, 16, 0, + 25, 0, 0, 0, 58, 0, + 16, 0, 25, 0, 0, 0, + 58, 144, 144, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 26, 0, 16, 0, 19, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 25, 0, + 0, 0, 18, 0, 0, 1, + 32, 0, 0, 7, 66, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 25, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 25, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 26, 0, 0, 0, 58, 0, + 16, 0, 23, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 26, 0, 0, 0, 70, 14, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 26, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 194, 0, + 16, 0, 25, 0, 0, 0, + 6, 4, 16, 0, 20, 0, + 0, 0, 6, 4, 16, 0, + 26, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 25, 0, 0, 0, 58, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 35, 0, 0, 9, + 66, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 26, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 35, 0, 0, 9, + 66, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 20, 0, 0, 0, 58, 0, + 16, 0, 26, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 33, 0, 0, 7, + 130, 0, 16, 0, 25, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 25, 0, 0, 0, 34, 0, + 0, 7, 18, 0, 16, 0, + 26, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 43, 0, 0, 5, + 66, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 56, 0, + 0, 7, 66, 0, 16, 0, + 25, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 14, 0, 0, 7, + 66, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 58, 0, + 16, 0, 15, 0, 0, 0, + 28, 0, 0, 5, 66, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 25, 0, + 0, 0, 10, 0, 16, 0, + 19, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 55, 0, 0, 10, 66, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 26, 0, + 0, 0, 58, 144, 144, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 26, 0, 16, 0, + 19, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 25, 0, 0, 0, 58, 0, + 16, 0, 25, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 18, 0, + 0, 1, 167, 0, 0, 9, + 242, 0, 16, 0, 26, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 7, + 242, 0, 16, 0, 26, 0, + 0, 0, 70, 14, 16, 0, + 24, 0, 0, 0, 70, 14, + 16, 0, 26, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 194, 0, 16, 0, + 25, 0, 0, 0, 6, 4, + 16, 0, 22, 0, 0, 0, + 6, 4, 16, 0, 26, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 25, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 35, 0, 0, 9, 66, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 22, 0, + 0, 0, 42, 0, 16, 0, + 26, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 35, 0, 0, 9, 66, 0, + 16, 0, 25, 0, 0, 0, + 58, 0, 16, 0, 22, 0, + 0, 0, 58, 0, 16, 0, + 26, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 33, 0, 0, 7, 130, 0, + 16, 0, 25, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 60, 0, + 0, 7, 130, 0, 16, 0, + 25, 0, 0, 0, 26, 0, + 16, 0, 23, 0, 0, 0, + 58, 0, 16, 0, 25, 0, + 0, 0, 34, 0, 0, 7, + 18, 0, 16, 0, 26, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 43, 0, 0, 5, 66, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 14, 0, 0, 7, 66, 0, + 16, 0, 25, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 23, 0, 0, 0, 28, 0, + 0, 5, 66, 0, 16, 0, + 25, 0, 0, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 55, 0, + 0, 10, 66, 0, 16, 0, + 25, 0, 0, 0, 10, 0, + 16, 0, 26, 0, 0, 0, + 58, 144, 144, 0, 42, 0, + 16, 0, 25, 0, 0, 0, + 26, 0, 16, 0, 19, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 25, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 30, 0, + 0, 7, 34, 0, 16, 0, + 25, 0, 0, 0, 42, 0, + 16, 0, 19, 0, 0, 0, + 26, 0, 16, 0, 25, 0, + 0, 0, 30, 0, 0, 10, + 66, 0, 16, 0, 25, 0, + 0, 0, 1, 64, 0, 0, + 64, 0, 0, 0, 10, 144, + 208, 128, 65, 0, 0, 0, + 64, 0, 0, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 41, 0, 0, 7, 18, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 25, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 54, 0, + 0, 7, 18, 0, 16, 0, + 26, 0, 0, 0, 10, 48, + 32, 4, 0, 0, 0, 0, + 10, 0, 16, 0, 25, 0, + 0, 0, 54, 0, 0, 8, + 34, 0, 16, 0, 26, 0, + 0, 0, 10, 48, 32, 6, + 0, 0, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 25, 0, 0, 0, 54, 0, + 0, 8, 66, 0, 16, 0, + 26, 0, 0, 0, 10, 48, + 32, 6, 0, 0, 0, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 25, 0, 0, 0, + 54, 0, 0, 7, 18, 0, + 16, 0, 27, 0, 0, 0, + 26, 48, 32, 4, 0, 0, + 0, 0, 10, 0, 16, 0, + 25, 0, 0, 0, 54, 0, + 0, 8, 34, 0, 16, 0, + 27, 0, 0, 0, 26, 48, + 32, 6, 0, 0, 0, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 25, 0, 0, 0, + 54, 0, 0, 8, 66, 0, + 16, 0, 27, 0, 0, 0, + 26, 48, 32, 6, 0, 0, + 0, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 25, 0, + 0, 0, 38, 0, 0, 10, + 0, 208, 0, 0, 178, 0, + 16, 0, 25, 0, 0, 0, + 70, 8, 16, 0, 27, 0, + 0, 0, 6, 144, 208, 0, + 64, 0, 0, 0, 26, 0, + 16, 0, 25, 0, 0, 0, + 35, 0, 0, 9, 114, 0, + 16, 0, 25, 0, 0, 0, + 166, 10, 16, 0, 25, 0, + 0, 0, 70, 2, 16, 0, + 26, 0, 0, 0, 70, 3, + 16, 0, 25, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 25, 0, 0, 0, + 70, 2, 16, 0, 25, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 178, 0, 16, 0, + 25, 0, 0, 0, 70, 8, + 16, 0, 25, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 26, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 114, 0, 16, 0, 27, 0, + 0, 0, 70, 3, 16, 0, + 25, 0, 0, 0, 70, 2, + 16, 0, 26, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 26, 0, + 0, 0, 55, 0, 0, 9, + 146, 0, 16, 0, 27, 0, + 0, 0, 6, 0, 16, 0, + 27, 0, 0, 0, 166, 2, + 16, 0, 25, 0, 0, 0, + 6, 8, 16, 0, 25, 0, + 0, 0, 54, 0, 0, 5, + 82, 0, 16, 0, 25, 0, + 0, 0, 86, 6, 16, 0, + 26, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 25, 0, 0, 0, 86, 10, + 16, 0, 27, 0, 0, 0, + 70, 14, 16, 0, 25, 0, + 0, 0, 22, 11, 16, 0, + 25, 0, 0, 0, 79, 0, + 0, 7, 18, 0, 16, 0, + 26, 0, 0, 0, 1, 64, + 0, 0, 255, 0, 0, 0, + 58, 0, 16, 0, 26, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 14, 0, + 0, 0, 58, 0, 16, 0, + 26, 0, 0, 0, 55, 0, + 0, 9, 146, 0, 16, 0, + 26, 0, 0, 0, 6, 0, + 16, 0, 26, 0, 0, 0, + 86, 1, 16, 0, 14, 0, + 0, 0, 6, 4, 16, 0, + 14, 0, 0, 0, 40, 0, + 0, 5, 18, 0, 16, 0, + 28, 0, 0, 0, 58, 0, + 16, 0, 27, 0, 0, 0, + 40, 0, 0, 5, 98, 0, + 16, 0, 28, 0, 0, 0, + 86, 7, 16, 0, 25, 0, + 0, 0, 40, 0, 0, 5, + 130, 0, 16, 0, 28, 0, + 0, 0, 10, 0, 16, 0, + 26, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 26, 0, 0, 0, 10, 0, + 16, 0, 27, 0, 0, 0, + 54, 0, 0, 5, 98, 0, + 16, 0, 26, 0, 0, 0, + 6, 2, 16, 0, 25, 0, + 0, 0, 30, 0, 0, 7, + 242, 0, 16, 0, 25, 0, + 0, 0, 70, 14, 16, 0, + 28, 0, 0, 0, 70, 14, + 16, 0, 26, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 50, 0, 16, 0, + 25, 0, 0, 0, 70, 0, + 16, 0, 25, 0, 0, 0, + 70, 0, 16, 0, 25, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 14, 0, + 0, 0, 26, 0, 16, 0, + 25, 0, 0, 0, 10, 0, + 16, 0, 25, 0, 0, 0, + 35, 0, 0, 9, 18, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 25, 0, + 0, 0, 42, 0, 16, 0, + 25, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 86, 0, 0, 5, 18, 0, + 16, 0, 14, 0, 0, 0, + 10, 0, 16, 0, 14, 0, + 0, 0, 86, 0, 0, 5, + 18, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 25, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 25, 0, 0, 0, 10, 0, + 16, 0, 25, 0, 0, 0, + 10, 0, 16, 0, 25, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 14, 0, + 0, 0, 10, 0, 16, 0, + 25, 0, 0, 0, 42, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 28, 0, 0, 5, 18, 0, + 16, 0, 14, 0, 0, 0, + 10, 0, 16, 0, 14, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 16, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 26, 0, + 16, 0, 16, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 23, 0, 0, 0, + 58, 0, 16, 0, 23, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 79, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 16, 0, 0, 0, 26, 0, + 16, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 50, 0, + 16, 0, 15, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 16, 0, 0, 0, 70, 0, + 16, 0, 15, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 16, 0, 0, 0, + 10, 0, 16, 0, 16, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 26, 0, 16, 0, + 15, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 10, 0, 16, 0, 15, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 32, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 32, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 79, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 31, 0, + 4, 3, 58, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 32, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 79, 0, 0, 9, 98, 0, + 16, 0, 0, 0, 0, 0, + 6, 64, 2, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 32, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 24, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 79, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 168, 0, + 0, 8, 18, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 24, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 168, 0, 0, 8, 18, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 9, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 6, 112, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 24, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 167, 0, 0, 9, + 242, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 126, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 168, 0, 0, 9, 242, 224, + 17, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 62, 0, + 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode02CS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode02CS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..071a42ca987fe4a7dd32a96950b75fc7a5f1ee39 Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode02CS.pdb differ diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode137CS.inc b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode137CS.inc new file mode 100644 index 0000000000000000000000000000000000000000..9a78e45a8948c01fc07ff005452bd91e72be5b26 --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode137CS.inc @@ -0,0 +1,3961 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { 0x0000cccc, 15, 0, 0}, + { 0x00008888, 15, 0, 0}, + { 0x0000eeee, 15, 0, 0}, + { 0x0000ecc8, 15, 0, 1}, + { 0x0000c880, 15, 0, 1}, + { 0x0000feec, 15, 0, 1}, + { 0x0000fec8, 15, 0, 1}, + { 0x0000ec80, 15, 0, 2}, + { 0x0000c800, 15, 0, 2}, + { 0x0000ffec, 15, 0, 2}, + { 0x0000fe80, 15, 0, 2}, + { 0x0000e800, 15, 0, 2}, + { 0x0000ffe8, 15, 0, 3}, + { 0x0000ff00, 15, 0, 3}, + { 0x0000fff0, 15, 0, 3}, + { 0x0000f000, 15, 0, 3}, + { 0x0000f710, 15, 0, 4}, + { 142, 2, 0, 4}, + { 0x00007100, 8, 0, 4}, + { 2254, 2, 0, 4}, + { 140, 2, 0, 5}, + { 0x00007310, 8, 0, 5}, + { 0x00003100, 8, 0, 5}, + { 0x00008cce, 15, 0, 5}, + { 2188, 2, 0, 6}, + { 0x00003110, 8, 0, 6}, + { 0x00006666, 2, 0, 6}, + { 0x0000366c, 2, 0, 6}, + { 6120, 8, 0, 6}, + { 4080, 8, 0, 7}, + { 0x0000718e, 2, 0, 7}, + { 0x0000399c, 2, 0, 7}, + { 0x0000aaaa, 15, 0, 7}, + { 0x0000f0f0, 15, 0, 8}, + { 0x00005a5a, 6, 0, 8}, + { 0x000033cc, 8, 0, 8}, + { 0x00003c3c, 2, 0, 8}, + { 0x000055aa, 8, 0, 9}, + { 0x00009696, 15, 0, 9}, + { 0x0000a55a, 15, 0, 9}, + { 0x000073ce, 2, 0, 9}, + { 5064, 8, 0, 10}, + { 0x0000324c, 2, 0, 10}, + { 0x00003bdc, 2, 0, 10}, + { 0x00006996, 2, 0, 10}, + { 0x0000c33c, 15, 0, 10}, + { 0x00009966, 15, 0, 11}, + { 1632, 6, 0, 11}, + { 626, 6, 0, 11}, + { 1252, 2, 0, 11}, + { 0x00004e40, 6, 0, 12}, + { 0x00002720, 8, 0, 12}, + { 0x0000c936, 15, 0, 12}, + { 0x0000936c, 15, 0, 12}, + { 0x000039c6, 2, 0, 13}, + { 0x0000639c, 2, 0, 13}, + { 0x00009336, 15, 0, 13}, + { 0x00009cc6, 15, 0, 13}, + { 0x0000817e, 15, 0, 14}, + { 0x0000e718, 15, 0, 14}, + { 0x0000ccf0, 15, 0, 14}, + { 4044, 2, 0, 14}, + { 0x00007744, 2, 0, 15}, + { 0x0000ee22, 15, 0, 15}, + { 0, 3, 15, 0}, + { 4, 3, 8, 0}, + { 9, 15, 8, 0}, + { 13, 15, 3, 0}, + { 17, 8, 15, 0}, + { 21, 3, 15, 1}, + { 26, 15, 3, 1}, + { 30, 15, 8, 1}, + { 34, 8, 15, 1}, + { 38, 8, 15, 1}, + { 43, 6, 15, 1}, + { 47, 6, 15, 1}, + { 51, 6, 15, 1}, + { 55, 5, 15, 1}, + { 60, 3, 15, 2}, + { 64, 3, 8, 2}, + { 0, 3, 15, 2}, + { 9, 3, 8, 2}, + { 18, 8, 15, 2}, + { 27, 15, 3, 2}, + { 37, 3, 15, 2}, + { 46, 3, 8, 2}, + { 55, 6, 15, 2}, + { 64, 10, 8, 3}, + { 0, 5, 3, 3}, + { 0, 8, 15, 3}, + { 0, 8, 6, 3}, + { 0, 6, 10, 3}, + { 0, 8, 15, 3}, + { 0, 5, 15, 3}, + { 0, 15, 10, 3}, + { 0, 15, 8, 3}, + { 0, 8, 15, 3}, + { 21, 15, 3, 4}, + { 43, 3, 15, 4}, + { 64, 5, 10, 4}, + { 0, 6, 10, 4}, + { 0, 10, 8, 4}, + { 0, 8, 9, 4}, + { 0, 15, 10, 4}, + { 0, 15, 6, 4}, + { 0, 3, 15, 4}, + { 0, 15, 8, 5}, + { 0, 5, 15, 5}, + { 0, 15, 3, 5}, + { 0, 15, 6, 5}, + { 0, 15, 6, 5}, + { 0, 15, 8, 5}, + { 0, 3, 15, 5}, + { 0, 15, 3, 5}, + { 0, 5, 15, 5}, + { 0, 5, 15, 6}, + { 0, 5, 15, 6}, + { 0, 8, 15, 6}, + { 0, 5, 15, 6}, + { 0, 10, 15, 6}, + { 0, 5, 15, 6}, + { 0, 10, 15, 6}, + { 0, 8, 15, 6}, + { 0, 13, 15, 6}, + { 0, 15, 3, 7}, + { 0, 12, 15, 7}, + { 0, 3, 15, 7}, + { 0, 3, 8, 7}, + { 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, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 1}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 2}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3}, + { 0, 0, 0, 3} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_structured t1, 16 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 29 +dcl_indexableTemp x0[8], 4 +dcl_tgsm_structured g0, 100, 64 +dcl_thread_group 64, 1, 1 +iadd r0.x, vThreadGroupID.x, cb0[1].x +ult r1.xyzw, vThreadIDInGroupFlattened.xxxx, l(16, 32, 8, 4) +if_nz r1.x + udiv r0.y, null, r0.x, cb0[0].y + imad r0.z, -r0.y, cb0[0].y, r0.x + ishl r0.z, r0.z, l(2) + ishl r0.y, r0.y, l(2) + and r0.w, vThreadIDInGroupFlattened.x, l(3) + iadd r2.x, r0.w, r0.z + ushr r0.z, vThreadIDInGroupFlattened.x, l(2) + iadd r2.y, r0.z, r0.y + mov r2.zw, l(0,0,0,0) + ld r2.xyzw, r2.xyzw, t0.xyzw + mul r2.xyzw, r2.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000) + ftou r2.xyzw, r2.xyzw + umin r2.xyzw, r2.xyzw, l(255, 255, 255, 255) + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(0), r2.xyzw +endif +sync_g_t +mov x0[0].x, l(-1) +mov x0[1].x, l(-1) +mov x0[2].x, l(-1) +mov x0[3].x, l(-1) +mov x0[0].y, l(0) +mov x0[1].y, l(0) +mov x0[2].y, l(0) +mov x0[3].y, l(0) +mov x0[4].x, l(-1) +mov x0[5].x, l(-1) +mov x0[6].x, l(-1) +mov x0[7].x, l(-1) +mov x0[4].y, l(0) +mov x0[5].y, l(0) +mov x0[6].y, l(0) +mov x0[7].y, l(0) +mov r0.y, l(0) +loop + uge r0.z, r0.y, l(16) + breakc_nz r0.z + ld_structured r2.xyzw, r0.y, l(0), g0.xyzw + mov r0.z, vThreadIDInGroupFlattened.x + ushr r0.z, icb[r0.z + 0].x, r0.y + and r0.z, r0.z, l(1) + ieq r0.z, r0.z, l(1) + if_nz r0.z + mov r3.x, x0[4].x + mov r3.y, x0[5].x + mov r3.z, x0[6].x + mov r3.w, x0[7].x + umin r3.xyzw, r2.xyzw, r3.xyzw + mov x0[4].x, r3.x + mov x0[5].x, r3.y + mov x0[6].x, r3.z + mov x0[7].x, r3.w + mov r3.x, x0[4].y + mov r3.y, x0[5].y + mov r3.z, x0[6].y + mov r3.w, x0[7].y + umax r3.xyzw, r2.xyzw, r3.xyzw + mov x0[4].y, r3.x + mov x0[5].y, r3.y + mov x0[6].y, r3.z + mov x0[7].y, r3.w + else + mov r3.x, x0[0].x + mov r3.y, x0[1].x + mov r3.z, x0[2].x + mov r3.w, x0[3].x + umin r3.xyzw, r2.xyzw, r3.xyzw + mov x0[0].x, r3.x + mov x0[1].x, r3.y + mov x0[2].x, r3.z + mov x0[3].x, r3.w + mov r3.x, x0[0].y + mov r3.y, x0[1].y + mov r3.z, x0[2].y + mov r3.w, x0[3].y + umax r2.xyzw, r2.xyzw, r3.xyzw + mov x0[0].y, r2.x + mov x0[1].y, r2.y + mov x0[2].y, r2.z + mov x0[3].y, r2.w + endif + iadd r0.y, r0.y, l(1) +endloop +mov r2.x, x0[0].x +mov r2.y, x0[1].x +mov r2.z, x0[2].x +mov r2.w, x0[3].x +mov r3.x, x0[0].y +mov r3.y, x0[1].y +mov r3.z, x0[2].y +mov r3.w, x0[3].y +mov r4.x, x0[4].x +mov r4.y, x0[5].x +mov r4.z, x0[6].x +mov r4.w, x0[7].x +mov r5.x, x0[4].y +mov r5.y, x0[5].y +mov r5.z, x0[6].y +mov r5.w, x0[7].y +ieq r0.y, cb0[0].w, l(1) +movc r0.y, r0.y, l(4), l(16) +iadd r6.xyz, r2.xyzx, l(1, 1, 1, 0) +umin r6.xyz, r6.xyzx, l(255, 255, 255, 0) +ushr r6.xyz, r6.xyzx, l(1) +and r6.xyz, r6.xyzx, l(126, 126, 126, 0) +iadd r7.xyz, r3.xyzx, l(1, 1, 1, 0) +umin r7.xyz, r7.xyzx, l(255, 255, 255, 0) +ushr r7.xyz, r7.xyzx, l(1) +and r7.xyz, r7.xyzx, l(126, 126, 126, 0) +iadd r8.xyz, r4.xyzx, l(1, 1, 1, 0) +and r9.xyz, r2.xyzx, l(-2, -2, -2, 0) +and r10.xyz, r3.xyzx, l(-2, -2, -2, 0) +umin r8.xyz, r8.xyzx, l(255, 255, 255, 0) +iadd r11.xyzw, r2.xyzw, l(2, 2, 2, 2) +umin r11.xyzw, r11.xyzw, l(255, 255, 255, 255) +ushr r11.xyzw, r11.xyzw, l(2) +and r11.xyzw, r11.xyzw, l(62, 62, 62, 62) +iadd r12.xyzw, r3.xyzw, l(2, 2, 2, 2) +umin r12.xyzw, r12.xyzw, l(255, 255, 255, 255) +ushr r12.xyzw, r12.xyzw, l(2) +and r12.xyzw, r12.xyzw, l(62, 62, 62, 62) +ushr r8.xyz, r8.xyzx, l(1) +and r8.xyz, r8.xyzx, l(126, 126, 126, 0) +iadd r13.xyz, r5.xyzx, l(1, 1, 1, 0) +umin r13.xyz, r13.xyzx, l(255, 255, 255, 0) +ushr r13.xyz, r13.xyzx, l(1) +and r13.xyz, r13.xyzx, l(126, 126, 126, 0) +and r14.xyz, r4.xyzx, l(-2, -2, -2, 0) +and r15.xyz, r5.xyzx, l(-2, -2, -2, 0) +iadd r16.xyzw, r4.xyzw, l(2, 2, 2, 2) +umin r16.xyzw, r16.xyzw, l(255, 255, 255, 255) +ushr r16.xyzw, r16.xyzw, l(2) +and r16.xyzw, r16.xyzw, l(62, 62, 62, 62) +iadd r17.xyzw, r5.xyzw, l(2, 2, 2, 2) +umin r17.xyzw, r17.xyzw, l(255, 255, 255, 255) +ushr r17.xyzw, r17.xyzw, l(2) +and r17.xyzw, r17.xyzw, l(62, 62, 62, 62) +mov r0.z, cb0[0].w +mov r0.w, l(0) +mov r18.y, l(-1) +mov r19.x, l(0) +loop + uge r6.w, r19.x, r0.y + breakc_nz r6.w + mov x0[0].x, r2.x + mov x0[1].x, r2.y + mov x0[2].x, r2.z + mov x0[3].x, r2.w + mov x0[0].y, r3.x + mov x0[1].y, r3.y + mov x0[2].y, r3.z + mov x0[3].y, r3.w + mov x0[4].x, r4.x + mov x0[5].x, r4.y + mov x0[6].x, r4.z + mov x0[7].x, r4.w + mov x0[4].y, r5.x + mov x0[5].y, r5.y + mov x0[6].y, r5.z + mov x0[7].y, r5.w + ieq r6.w, r0.z, l(1) + if_nz r6.w + and r6.w, r19.x, l(1) + iadd r20.xyz, r6.wwww, r6.xyzx + ishl r20.xyz, r20.xyzx, l(1) + ushr r21.xyz, r20.xyzx, l(7) + iadd r20.xyz, r20.xyzx, r21.xyzx + iadd r21.xyz, r6.wwww, r7.xyzx + ishl r21.xyz, r21.xyzx, l(1) + ushr r22.xyz, r21.xyzx, l(7) + iadd r21.xyz, r21.xyzx, r22.xyzx + mov x0[0].x, r20.x + mov x0[1].x, r20.y + mov x0[2].x, r20.z + mov x0[3].x, l(255) + mov x0[0].y, r21.x + mov x0[1].y, r21.y + mov x0[2].y, r21.z + mov x0[3].y, l(255) + ushr r6.w, r19.x, l(1) + and r6.w, r6.w, l(1) + iadd r20.xyz, r6.wwww, r8.xyzx + ishl r20.xyz, r20.xyzx, l(1) + ushr r21.xyz, r20.xyzx, l(7) + iadd r20.xyz, r20.xyzx, r21.xyzx + iadd r21.xyz, r6.wwww, r13.xyzx + ishl r21.xyz, r21.xyzx, l(1) + ushr r22.xyz, r21.xyzx, l(7) + iadd r21.xyz, r21.xyzx, r22.xyzx + mov x0[4].x, r20.x + mov x0[5].x, r20.y + mov x0[6].x, r20.z + mov x0[7].x, l(255) + mov x0[4].y, r21.x + mov x0[5].y, r21.y + mov x0[6].y, r21.z + mov x0[7].y, l(255) + else + ieq r6.w, r0.z, l(3) + if_nz r6.w + ushr r19.y, r19.x, l(1) + and r19.zw, r19.xxxy, l(0, 0, 1, 1) + iadd r20.xyz, r9.xyzx, r19.zzzz + iadd r21.xyz, r10.xyzx, r19.wwww + mov x0[0].x, r20.x + mov x0[1].x, r20.y + mov x0[2].x, r20.z + mov x0[3].x, l(255) + mov x0[0].y, r21.x + mov x0[1].y, r21.y + mov x0[2].y, r21.z + mov x0[3].y, l(255) + else + ieq r7.w, r0.z, l(7) + if_nz r7.w + ushr r19.y, r19.x, l(1) + and r19.zw, r19.xxxy, l(0, 0, 1, 1) + iadd r20.xyzw, r11.xyzw, r19.zzzz + ishl r20.xyzw, r20.xyzw, l(2) + ushr r21.xyzw, r20.xyzw, l(6) + iadd r20.xyzw, r20.xyzw, r21.xyzw + iadd r21.xyzw, r12.xyzw, r19.wwww + ishl r21.xyzw, r21.xyzw, l(2) + ushr r22.xyzw, r21.xyzw, l(6) + iadd r21.xyzw, r21.xyzw, r22.xyzw + mov x0[0].x, r20.x + mov x0[1].x, r20.y + mov x0[2].x, r20.z + mov x0[3].x, r20.w + mov x0[0].y, r21.x + mov x0[1].y, r21.y + mov x0[2].y, r21.z + mov x0[3].y, r21.w + endif + endif + if_nz r6.w + ushr r20.x, r19.x, l(2) + ushr r20.y, r19.x, l(3) + and r19.zw, r20.xxxy, l(0, 0, 1, 1) + iadd r20.xyz, r14.xyzx, r19.zzzz + iadd r21.xyz, r15.xyzx, r19.wwww + mov x0[4].x, r20.x + mov x0[5].x, r20.y + mov x0[6].x, r20.z + mov x0[7].x, l(255) + mov x0[4].y, r21.x + mov x0[5].y, r21.y + mov x0[6].y, r21.z + mov x0[7].y, l(255) + else + ieq r6.w, r0.z, l(7) + if_nz r6.w + ushr r20.x, r19.x, l(2) + ushr r20.y, r19.x, l(3) + and r19.zw, r20.xxxy, l(0, 0, 1, 1) + iadd r20.xyzw, r16.xyzw, r19.zzzz + ishl r20.xyzw, r20.xyzw, l(2) + ushr r21.xyzw, r20.xyzw, l(6) + iadd r20.xyzw, r20.xyzw, r21.xyzw + iadd r21.xyzw, r17.xyzw, r19.wwww + ishl r21.xyzw, r21.xyzw, l(2) + ushr r22.xyzw, r21.xyzw, l(6) + iadd r21.xyzw, r21.xyzw, r22.xyzw + mov x0[4].x, r20.x + mov x0[5].x, r20.y + mov x0[6].x, r20.z + mov x0[7].x, r20.w + mov x0[4].y, r21.x + mov x0[5].y, r21.y + mov x0[6].y, r21.z + mov x0[7].y, r21.w + endif + endif + endif + mov r20.x, x0[0].y + mov r20.y, x0[1].y + mov r20.z, x0[2].y + mov r20.w, x0[3].y + mov r6.w, x0[0].x + mov r7.w, x0[1].x + mov r8.w, x0[2].x + mov r9.w, x0[3].x + ineg r21.x, r6.w + ineg r21.y, r7.w + ineg r21.z, r8.w + ineg r21.w, r9.w + iadd r22.xyzw, r20.xyzw, r21.xyzw + mov r23.x, x0[4].y + mov r23.y, x0[5].y + mov r23.z, x0[6].y + mov r23.w, x0[7].y + mov r10.w, x0[4].x + mov r13.w, x0[5].x + mov r14.w, x0[6].x + mov r15.w, x0[7].x + ineg r24.x, r10.w + ineg r24.y, r13.w + ineg r24.z, r14.w + ineg r24.w, r15.w + iadd r23.xyzw, r23.xyzw, r24.xyzw + ine r19.zw, r0.zzzz, l(0, 0, 7, 1) + movc r23.w, r19.z, l(0), r23.w + movc r22.w, r19.z, l(0), r22.w + imul null, r24.xy, r22.xyxx, r22.xyxx + iadd r10.w, r24.y, r24.x + imad r10.w, r22.z, r22.z, r10.w + imad r10.w, r22.w, r22.w, r10.w + imul null, r24.xy, r23.xyxx, r23.xyxx + iadd r13.w, r24.y, r24.x + imad r13.w, r23.z, r23.z, r13.w + imad r13.w, r23.w, r23.w, r13.w + ld_structured r24.xyzw, l(0), l(0), g0.xyzw + iadd r21.xyzw, r21.xyzw, r24.xyzw + imul null, r21.xy, r21.xyxx, r22.xyxx + iadd r14.w, r21.y, r21.x + imad r14.w, r22.z, r21.z, r14.w + imad r14.w, r22.w, r21.w, r14.w + ilt r15.w, l(0), r10.w + ilt r18.w, l(0), r14.w + and r15.w, r15.w, r18.w + itof r14.w, r14.w + mul r14.w, r14.w, l(63.499989) + ftou r14.w, r14.w + ishl r18.w, r10.w, l(5) + ult r14.w, r18.w, r14.w + and r14.w, r14.w, r15.w + ineg r21.xyzw, r22.xyzw + movc r21.xyzw, r14.wwww, r21.xyzw, r22.xyzw + movc r15.w, r14.w, r20.x, r6.w + mov x0[0].x, r15.w + mov r18.w, x0[1].x + movc r18.w, r14.w, r20.y, r18.w + mov x0[1].x, r18.w + mov r20.x, x0[2].x + movc r20.x, r14.w, r20.z, r20.x + mov x0[2].x, r20.x + mov r20.y, x0[3].x + movc r20.y, r14.w, r20.w, r20.y + mov x0[3].x, r20.y + mov r20.z, x0[0].y + movc r6.w, r14.w, r6.w, r20.z + mov x0[0].y, r6.w + mov r6.w, x0[1].y + movc r6.w, r14.w, r7.w, r6.w + mov x0[1].y, r6.w + mov r6.w, x0[2].y + movc r6.w, r14.w, r8.w, r6.w + mov x0[2].y, r6.w + mov r6.w, x0[3].y + movc r6.w, r14.w, r9.w, r6.w + mov x0[3].y, r6.w + mov r6.w, vThreadIDInGroupFlattened.x + mov r7.w, icb[r6.w + 0].y + ld_structured r22.xyzw, r7.w, l(0), g0.xyzw + mov r7.w, x0[4].x + mov r8.w, x0[5].x + mov r9.w, x0[6].x + mov r14.w, x0[7].x + ineg r24.x, r7.w + ineg r24.y, r8.w + ineg r24.z, r9.w + ineg r24.w, r14.w + iadd r22.xyzw, r22.xyzw, r24.xyzw + imul null, r20.zw, r22.xxxy, r23.xxxy + iadd r20.z, r20.w, r20.z + imad r20.z, r23.z, r22.z, r20.z + imad r20.z, r23.w, r22.w, r20.z + ilt r20.w, l(0), r13.w + ilt r22.x, l(0), r20.z + and r20.w, r20.w, r22.x + itof r20.z, r20.z + mul r20.z, r20.z, l(63.499989) + ftou r20.z, r20.z + ishl r22.x, r13.w, l(5) + ult r20.z, r22.x, r20.z + and r20.z, r20.z, r20.w + ineg r22.xyzw, r23.xyzw + movc r22.xyzw, r20.zzzz, r22.xyzw, r23.xyzw + mov r20.w, x0[4].y + mov r23.x, x0[5].y + mov r23.y, x0[6].y + mov r23.z, x0[7].y + movc r20.w, r20.z, r20.w, r7.w + mov x0[4].x, r20.w + mov r23.w, x0[5].x + movc r23.x, r20.z, r23.x, r23.w + mov x0[5].x, r23.x + mov r23.w, x0[6].x + movc r23.y, r20.z, r23.y, r23.w + mov x0[6].x, r23.y + mov r23.w, x0[7].x + movc r23.z, r20.z, r23.z, r23.w + mov x0[7].x, r23.z + mov r23.w, x0[4].y + movc r7.w, r20.z, r7.w, r23.w + mov x0[4].y, r7.w + mov r7.w, x0[5].y + movc r7.w, r20.z, r8.w, r7.w + mov x0[5].y, r7.w + mov r7.w, x0[6].y + movc r7.w, r20.z, r9.w, r7.w + mov x0[6].y, r7.w + mov r7.w, x0[7].y + movc r7.w, r20.z, r14.w, r7.w + mov x0[7].y, r7.w + ineg r24.x, r20.w + ineg r24.yzw, r23.xxyz + ige r7.w, l(0), r13.w + itof r8.w, r13.w + movc r23.xyz, r19.wwww, l(32,128,3,0), l(16,64,7,0) + ineg r25.x, r15.w + ineg r25.y, r18.w + ineg r25.zw, r20.xxxy + ige r9.w, l(0), r10.w + itof r14.w, r10.w + mov r15.w, l(0) + mov r19.y, l(0) + loop + uge r18.w, r15.w, l(16) + breakc_nz r18.w + ushr r18.w, icb[r6.w + 0].x, r15.w + and r18.w, r18.w, l(1) + ieq r19.w, r18.w, l(1) + if_nz r19.w + ld_structured r20.xyzw, r15.w, l(0), g0.xyzw + iadd r20.xyzw, r24.xyzw, r20.xyzw + imul null, r20.xy, r20.xyxx, r22.xyxx + iadd r19.w, r20.y, r20.x + imad r19.w, r22.z, r20.z, r19.w + imad r19.w, r22.w, r20.w, r19.w + ige r20.x, l(0), r19.w + or r20.x, r7.w, r20.x + ilt r20.y, r19.w, r13.w + itof r19.w, r19.w + mul r19.w, r19.w, l(63.499989) + div r19.w, r19.w, r8.w + ftou r19.w, r19.w + iadd r19.w, r19.w, r23.y + movc r19.w, r20.y, icb[r19.w + 0].w, r23.z + movc r19.w, r20.x, l(0), r19.w + else + ld_structured r20.xyzw, r15.w, l(0), g0.xyzw + iadd r20.xyzw, r25.xyzw, r20.xyzw + imul null, r20.xy, r20.xyxx, r21.xyxx + iadd r20.x, r20.y, r20.x + imad r20.x, r21.z, r20.z, r20.x + imad r20.x, r21.w, r20.w, r20.x + ige r20.y, l(0), r20.x + or r20.y, r9.w, r20.y + ilt r20.z, r20.x, r10.w + itof r20.x, r20.x + mul r20.x, r20.x, l(63.499989) + div r20.x, r20.x, r14.w + ftou r20.x, r20.x + iadd r20.x, r20.x, r23.y + movc r20.x, r20.z, icb[r20.x + 0].w, r23.z + movc r19.w, r20.y, l(0), r20.x + endif + iadd r19.w, r19.w, r23.x + iadd r20.x, l(64), -icb[r19.w + 64].x + ishl r18.w, r18.w, l(2) + mov r26.x, x0[r18.w + 0].x + mov r26.y, x0[r18.w + 1].x + mov r26.z, x0[r18.w + 2].x + mov r26.w, x0[r18.w + 3].x + mov r27.x, x0[r18.w + 0].y + mov r27.y, x0[r18.w + 1].y + mov r27.z, x0[r18.w + 2].y + mov r27.w, x0[r18.w + 3].y + imul null, r27.xyzw, r27.xyzw, icb[r19.w + 64].xxxx + imad r20.xyzw, r20.xxxx, r26.xyzw, r27.xyzw + iadd r20.xyzw, r20.xyzw, l(32, 32, 32, 32) + ushr r20.xyzw, r20.xzyw, l(6) + movc r20.w, r19.z, l(255), r20.w + ld_structured r26.xyzw, r15.w, l(0), g0.xyzw + ult r27.xyz, r20.xzyx, r26.xyzx + mov r28.xz, r26.xxyx + mov r28.yw, r20.xxxz + movc r28.xyzw, r27.xxyy, r28.xyzw, r28.yxwz + mov r20.xz, r26.zzwz + movc r20.xy, r27.zzzz, r20.xyxx, r20.yxyy + ult r18.w, r20.w, r26.w + movc r26.xw, r18.wwww, r20.wwwz, r20.zzzw + ineg r27.xy, r28.ywyy + ineg r27.z, r20.y + ineg r27.w, r26.x + mov r26.xy, r28.xzxx + mov r26.z, r20.x + iadd r20.xyzw, r27.xyzw, r26.xyzw + imul null, r20.xy, r20.xyxx, r20.xyxx + iadd r18.w, r20.y, r20.x + imad r18.w, r20.z, r20.z, r18.w + utof r18.w, r18.w + utof r19.w, r20.w + mul r19.w, r19.w, r19.w + mad r18.w, r19.w, cb0[1].z, r18.w + ftou r18.w, r18.w + iadd r19.y, r18.w, r19.y + iadd r15.w, r15.w, l(1) + endloop + ult r6.w, r19.y, r18.y + mov r18.x, r0.w + movc r18.xy, r6.wwww, r19.xyxx, r18.xyxx + iadd r19.x, r19.x, l(1) + mov r0.w, r18.x +endloop +mov r18.x, cb0[0].w +mov r18.z, vThreadIDInGroupFlattened.x +store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r18.yxzy +store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r0.w +sync_g_t +if_nz r1.y + iadd r0.y, vThreadIDInGroupFlattened.x, l(32) + ld_structured r2.yzw, r0.y, l(16), g0.xxyz + ld_structured r3.x, r0.y, l(32), g0.xxxx + ult r0.z, r2.y, r18.y + if_nz r0.z + ld_structured r2.x, r0.y, l(16), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r2.xzwx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r3.x + endif +endif +if_nz r1.x + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(16) + ld_structured r3.yzw, r0.y, l(16), g0.xxyz + ld_structured r4.x, r0.y, l(32), g0.xxxx + ult r0.z, r3.y, r2.x + if_nz r0.z + ld_structured r3.x, r0.y, l(16), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r3.xzwx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r4.x + endif +endif +if_nz r1.z + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(8) + ld_structured r3.yzw, r0.y, l(16), g0.xxyz + ld_structured r4.x, r0.y, l(32), g0.xxxx + ult r0.z, r3.y, r2.x + if_nz r0.z + ld_structured r3.x, r0.y, l(16), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r3.xzwx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r4.x + endif +endif +if_nz r1.w + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(4) + ld_structured r2.yzw, r0.y, l(16), g0.xxyz + ld_structured r3.x, r0.y, l(32), g0.xxxx + ult r0.z, r2.y, r1.x + if_nz r0.z + ld_structured r2.x, r0.y, l(16), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r2.xzwx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r3.x + endif +endif +ult r0.yz, vThreadIDInGroupFlattened.xxxx, l(0, 2, 1, 0) +if_nz r0.y + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(2) + ld_structured r2.yzw, r0.y, l(16), g0.xxyz + ld_structured r3.x, r0.y, l(32), g0.xxxx + ult r0.w, r2.y, r1.x + if_nz r0.w + ld_structured r2.x, r0.y, l(16), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r2.xzwx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r3.x + endif +endif +if_nz r0.z + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(1) + ld_structured r2.yzw, r0.y, l(16), g0.xxyz + ld_structured r3.x, r0.y, l(32), g0.xxxx + ult r0.z, r2.y, r1.x + if_nz r0.z + ld_structured r2.x, r0.y, l(16), g0.xxxx + store_structured g0.xyz, vThreadIDInGroupFlattened.x, l(16), r2.xzwx + store_structured g0.x, vThreadIDInGroupFlattened.x, l(32), r3.x + endif + ld_structured r1.x, r0.x, l(0), t1.xxxx + ld_structured r2.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + ult r0.y, r2.x, r1.x + if_nz r0.y + ld_structured r1.xyz, vThreadIDInGroupFlattened.x, l(16), g0.xyzx + ld_structured r1.w, vThreadIDInGroupFlattened.x, l(32), g0.xxxx + else + ld_structured r1.xyzw, r0.x, l(0), t1.xyzw + endif + store_structured u0.xyzw, r0.x, l(0), r1.xyzw +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC7Encode_TryMode137CS[] = +{ + 68, 88, 66, 67, 24, 142, + 44, 233, 135, 73, 185, 32, + 139, 70, 101, 2, 121, 203, + 167, 180, 1, 0, 0, 0, + 144, 73, 0, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 60, 73, 0, 0, + 64, 0, 5, 0, 79, 18, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 2, 3, + 0, 0, 204, 204, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 136, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 238, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 236, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 128, 200, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 236, 254, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 200, 254, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 128, 236, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 200, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 236, 255, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 128, 254, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 232, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 232, 255, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 255, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 240, 255, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 240, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 247, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 142, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 113, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 206, 8, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 140, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 16, 115, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 49, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 206, 140, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 140, 8, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 16, 49, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 102, 102, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 108, 54, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 232, 23, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 240, 15, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 142, 113, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 156, 57, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 170, 170, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 240, 240, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 90, 90, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 204, 51, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 60, 60, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 170, 85, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 150, 150, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 90, 165, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 206, 115, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 200, 19, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 76, 50, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 220, 59, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 150, 105, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 60, 195, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 102, 153, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 96, 6, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 114, 2, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 228, 4, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 64, 78, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 32, 39, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 54, 201, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 108, 147, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 198, 57, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 156, 99, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 54, 147, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 198, 156, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 126, 129, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 24, 231, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 240, 204, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 204, 15, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 68, 119, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 34, 238, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 15, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 0, 15, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 34, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 38, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 0, 43, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 0, 47, 0, 0, 0, + 6, 0, 0, 0, 15, 0, + 0, 0, 1, 0, 0, 0, + 51, 0, 0, 0, 6, 0, + 0, 0, 15, 0, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 1, 0, + 0, 0, 60, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 64, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 2, 0, + 0, 0, 9, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 18, 0, 0, 0, 8, 0, + 0, 0, 15, 0, 0, 0, + 2, 0, 0, 0, 27, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 37, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 2, 0, 0, 0, + 46, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 55, 0, + 0, 0, 6, 0, 0, 0, + 15, 0, 0, 0, 2, 0, + 0, 0, 64, 0, 0, 0, + 10, 0, 0, 0, 8, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 6, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 10, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 10, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 8, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 21, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 4, 0, 0, 0, 43, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 4, 0, + 0, 0, 64, 0, 0, 0, + 5, 0, 0, 0, 10, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 10, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 9, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 10, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 8, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 3, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 8, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 3, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 15, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 15, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 15, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 3, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 15, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 7, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 162, 0, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 0, 158, 0, 0, 4, + 0, 224, 17, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 95, 0, 0, 2, 0, 64, + 2, 0, 95, 0, 0, 2, + 18, 16, 2, 0, 104, 0, + 0, 2, 29, 0, 0, 0, + 105, 0, 0, 4, 0, 0, + 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 160, 0, + 0, 5, 0, 240, 17, 0, + 0, 0, 0, 0, 100, 0, + 0, 0, 64, 0, 0, 0, + 155, 0, 0, 4, 64, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 16, + 2, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 79, 0, 0, 9, + 242, 0, 16, 0, 1, 0, + 0, 0, 6, 64, 2, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 32, 0, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 78, 0, 0, 9, + 34, 0, 16, 0, 0, 0, + 0, 0, 0, 208, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 11, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 85, 0, + 0, 6, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 7, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 127, 67, 0, 0, 127, 67, + 28, 0, 0, 5, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 84, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 190, 24, 0, 1, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 42, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 54, 0, 0, 4, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 85, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 144, 144, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 32, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 84, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 6, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 3, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 84, 0, + 0, 7, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 30, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 54, 0, 0, 6, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 2, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 3, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 4, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 54, 0, 0, 6, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 34, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 5, 0, 0, 0, + 26, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 32, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 84, 0, 0, 10, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 126, 0, 0, 0, + 126, 0, 0, 0, 126, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 126, 0, 0, 0, 126, 0, + 0, 0, 126, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 254, 255, 255, 255, + 254, 255, 255, 255, 254, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 254, 255, 255, 255, 254, 255, + 255, 255, 254, 255, 255, 255, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 84, 0, 0, 10, 242, 0, + 16, 0, 11, 0, 0, 0, + 70, 14, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 85, 0, + 0, 7, 242, 0, 16, 0, + 11, 0, 0, 0, 70, 14, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 2, 64, + 0, 0, 62, 0, 0, 0, + 62, 0, 0, 0, 62, 0, + 0, 0, 62, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 12, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 84, 0, + 0, 10, 242, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 12, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 85, 0, 0, 7, + 242, 0, 16, 0, 12, 0, + 0, 0, 70, 14, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 12, 0, 0, 0, + 70, 14, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 62, 0, 0, 0, 62, 0, + 0, 0, 62, 0, 0, 0, + 62, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 126, 0, 0, 0, + 126, 0, 0, 0, 126, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 13, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 13, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 126, 0, 0, 0, 126, 0, + 0, 0, 126, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 14, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 254, 255, + 255, 255, 254, 255, 255, 255, + 254, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 254, 255, 255, 255, + 254, 255, 255, 255, 254, 255, + 255, 255, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 16, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 84, 0, + 0, 10, 242, 0, 16, 0, + 16, 0, 0, 0, 70, 14, + 16, 0, 16, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 85, 0, 0, 7, + 242, 0, 16, 0, 16, 0, + 0, 0, 70, 14, 16, 0, + 16, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 16, 0, 0, 0, + 70, 14, 16, 0, 16, 0, + 0, 0, 2, 64, 0, 0, + 62, 0, 0, 0, 62, 0, + 0, 0, 62, 0, 0, 0, + 62, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 17, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 84, 0, 0, 10, + 242, 0, 16, 0, 17, 0, + 0, 0, 70, 14, 16, 0, + 17, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 85, 0, 0, 7, 242, 0, + 16, 0, 17, 0, 0, 0, + 70, 14, 16, 0, 17, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 17, 0, 0, 0, 70, 14, + 16, 0, 17, 0, 0, 0, + 2, 64, 0, 0, 62, 0, + 0, 0, 62, 0, 0, 0, + 62, 0, 0, 0, 62, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 18, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 18, 0, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 1, + 80, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 3, 0, + 4, 3, 58, 0, 16, 0, + 6, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 32, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 58, 0, 16, 0, 6, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 246, 15, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 41, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 21, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 21, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 21, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 22, 0, 0, 0, + 70, 2, 16, 0, 21, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 21, 0, 0, 0, + 70, 2, 16, 0, 22, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 255, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 255, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 41, 0, 0, 7, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 21, 0, 0, 0, + 70, 2, 16, 0, 20, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 21, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 246, 15, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 41, 0, 0, 7, 114, 0, + 16, 0, 21, 0, 0, 0, + 70, 2, 16, 0, 21, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 22, 0, 0, 0, 70, 2, + 16, 0, 21, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 21, 0, 0, 0, 70, 2, + 16, 0, 22, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 255, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 255, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 31, 0, 4, 3, + 58, 0, 16, 0, 6, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 19, 0, + 0, 0, 10, 0, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 19, 0, 0, 0, + 6, 4, 16, 0, 19, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 20, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 166, 10, 16, 0, 19, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 21, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 246, 15, + 16, 0, 19, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 255, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 255, 0, 0, 0, + 18, 0, 0, 1, 32, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 7, 0, + 0, 0, 31, 0, 4, 3, + 58, 0, 16, 0, 7, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 19, 0, + 0, 0, 10, 0, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 19, 0, 0, 0, + 6, 4, 16, 0, 19, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 20, 0, 0, 0, 70, 14, + 16, 0, 11, 0, 0, 0, + 166, 10, 16, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 242, 0, 16, 0, 20, 0, + 0, 0, 70, 14, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 242, 0, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 20, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 20, 0, 0, 0, 70, 14, + 16, 0, 20, 0, 0, 0, + 70, 14, 16, 0, 21, 0, + 0, 0, 30, 0, 0, 7, + 242, 0, 16, 0, 21, 0, + 0, 0, 70, 14, 16, 0, + 12, 0, 0, 0, 246, 15, + 16, 0, 19, 0, 0, 0, + 41, 0, 0, 7, 242, 0, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 21, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 242, 0, 16, 0, + 22, 0, 0, 0, 70, 14, + 16, 0, 21, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 30, 0, 0, 7, + 242, 0, 16, 0, 21, 0, + 0, 0, 70, 14, 16, 0, + 21, 0, 0, 0, 70, 14, + 16, 0, 22, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 18, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 20, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 21, 0, 0, 0, + 54, 0, 0, 6, 34, 48, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 21, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 31, 0, 4, 3, + 58, 0, 16, 0, 6, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 20, 0, + 0, 0, 10, 0, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 34, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 10, 194, 0, 16, 0, + 19, 0, 0, 0, 6, 4, + 16, 0, 20, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 20, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 166, 10, + 16, 0, 19, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 21, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 246, 15, 16, 0, + 19, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 20, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 20, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 255, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 21, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 21, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 21, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 255, 0, 0, 0, 18, 0, + 0, 1, 32, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 6, 0, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 19, 0, + 0, 0, 1, 64, 0, 0, + 2, 0, 0, 0, 85, 0, + 0, 7, 34, 0, 16, 0, + 20, 0, 0, 0, 10, 0, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 19, 0, + 0, 0, 6, 4, 16, 0, + 20, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 20, 0, 0, 0, + 70, 14, 16, 0, 16, 0, + 0, 0, 166, 10, 16, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 242, 0, 16, 0, + 20, 0, 0, 0, 70, 14, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 242, 0, 16, 0, 21, 0, + 0, 0, 70, 14, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 20, 0, 0, 0, + 70, 14, 16, 0, 20, 0, + 0, 0, 70, 14, 16, 0, + 21, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 21, 0, 0, 0, 70, 14, + 16, 0, 17, 0, 0, 0, + 246, 15, 16, 0, 19, 0, + 0, 0, 41, 0, 0, 7, + 242, 0, 16, 0, 21, 0, + 0, 0, 70, 14, 16, 0, + 21, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 85, 0, 0, 7, 242, 0, + 16, 0, 22, 0, 0, 0, + 70, 14, 16, 0, 21, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 21, 0, 0, 0, 70, 14, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 22, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 21, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 6, + 18, 0, 16, 0, 20, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 20, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 20, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 20, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 7, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 8, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 9, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 40, 0, 0, 5, + 18, 0, 16, 0, 21, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 40, 0, + 0, 5, 34, 0, 16, 0, + 21, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 40, 0, 0, 5, 66, 0, + 16, 0, 21, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 40, 0, 0, 5, + 130, 0, 16, 0, 21, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 22, 0, 0, 0, 70, 14, + 16, 0, 20, 0, 0, 0, + 70, 14, 16, 0, 21, 0, + 0, 0, 54, 0, 0, 6, + 18, 0, 16, 0, 23, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 23, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 23, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 23, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 10, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 13, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 14, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 15, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 40, 0, 0, 5, + 18, 0, 16, 0, 24, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 40, 0, + 0, 5, 34, 0, 16, 0, + 24, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 40, 0, 0, 5, 66, 0, + 16, 0, 24, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 40, 0, 0, 5, + 130, 0, 16, 0, 24, 0, + 0, 0, 58, 0, 16, 0, + 15, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 23, 0, 0, 0, 70, 14, + 16, 0, 23, 0, 0, 0, + 70, 14, 16, 0, 24, 0, + 0, 0, 39, 0, 0, 10, + 194, 0, 16, 0, 19, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 23, 0, 0, 0, + 42, 0, 16, 0, 19, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 23, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 22, 0, 0, 0, + 42, 0, 16, 0, 19, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 22, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 50, 0, 16, 0, + 24, 0, 0, 0, 70, 0, + 16, 0, 22, 0, 0, 0, + 70, 0, 16, 0, 22, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 24, 0, 0, 0, 10, 0, + 16, 0, 24, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 22, 0, + 0, 0, 42, 0, 16, 0, + 22, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 22, 0, + 0, 0, 58, 0, 16, 0, + 22, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 50, 0, 16, 0, + 24, 0, 0, 0, 70, 0, + 16, 0, 23, 0, 0, 0, + 70, 0, 16, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 13, 0, + 0, 0, 26, 0, 16, 0, + 24, 0, 0, 0, 10, 0, + 16, 0, 24, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 13, 0, 0, 0, + 42, 0, 16, 0, 23, 0, + 0, 0, 42, 0, 16, 0, + 23, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 23, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 24, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 21, 0, + 0, 0, 70, 14, 16, 0, + 24, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 50, 0, 16, 0, 21, 0, + 0, 0, 70, 0, 16, 0, + 21, 0, 0, 0, 70, 0, + 16, 0, 22, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 14, 0, 0, 0, + 26, 0, 16, 0, 21, 0, + 0, 0, 10, 0, 16, 0, + 21, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 22, 0, 0, 0, + 42, 0, 16, 0, 21, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 22, 0, 0, 0, + 58, 0, 16, 0, 21, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 34, 0, + 0, 7, 130, 0, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 34, 0, 0, 7, + 130, 0, 16, 0, 18, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 14, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 15, 0, 0, 0, + 58, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 43, 0, + 0, 5, 130, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 14, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 14, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 28, 0, + 0, 5, 130, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 14, 0, 0, 0, + 41, 0, 0, 7, 130, 0, + 16, 0, 18, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 79, 0, + 0, 7, 130, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 14, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 15, 0, 0, 0, + 40, 0, 0, 5, 242, 0, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 22, 0, + 0, 0, 55, 0, 0, 9, + 242, 0, 16, 0, 21, 0, + 0, 0, 246, 15, 16, 0, + 14, 0, 0, 0, 70, 14, + 16, 0, 21, 0, 0, 0, + 70, 14, 16, 0, 22, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 15, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 18, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 54, 0, 0, 6, + 18, 0, 16, 0, 20, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 18, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 34, 0, 16, 0, 20, 0, + 0, 0, 10, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 55, 0, 0, 9, + 34, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 20, 0, 0, 0, + 26, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 18, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 66, 0, 16, 0, 20, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 48, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 55, 0, 0, 9, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 6, + 34, 48, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 4, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 64, 2, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 144, 144, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 22, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 7, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 8, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 9, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 54, 0, 0, 6, 130, 0, + 16, 0, 14, 0, 0, 0, + 10, 48, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 40, 0, 0, 5, 18, 0, + 16, 0, 24, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 40, 0, 0, 5, + 34, 0, 16, 0, 24, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 40, 0, + 0, 5, 66, 0, 16, 0, + 24, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 40, 0, 0, 5, 130, 0, + 16, 0, 24, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 30, 0, 0, 7, + 242, 0, 16, 0, 22, 0, + 0, 0, 70, 14, 16, 0, + 22, 0, 0, 0, 70, 14, + 16, 0, 24, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 194, 0, 16, 0, + 20, 0, 0, 0, 6, 4, + 16, 0, 22, 0, 0, 0, + 6, 4, 16, 0, 23, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 35, 0, 0, 9, 66, 0, + 16, 0, 20, 0, 0, 0, + 42, 0, 16, 0, 23, 0, + 0, 0, 42, 0, 16, 0, + 22, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 35, 0, 0, 9, 66, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 23, 0, + 0, 0, 58, 0, 16, 0, + 22, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 34, 0, 0, 7, 130, 0, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 34, 0, + 0, 7, 18, 0, 16, 0, + 22, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 20, 0, 0, 0, 10, 0, + 16, 0, 22, 0, 0, 0, + 43, 0, 0, 5, 66, 0, + 16, 0, 20, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 20, 0, + 0, 0, 42, 0, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 28, 0, 0, 5, 66, 0, + 16, 0, 20, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 41, 0, 0, 7, + 18, 0, 16, 0, 22, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 22, 0, + 0, 0, 42, 0, 16, 0, + 20, 0, 0, 0, 1, 0, + 0, 7, 66, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 20, 0, + 0, 0, 40, 0, 0, 5, + 242, 0, 16, 0, 22, 0, + 0, 0, 70, 14, 16, 0, + 23, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 22, 0, 0, 0, 166, 10, + 16, 0, 20, 0, 0, 0, + 70, 14, 16, 0, 22, 0, + 0, 0, 70, 14, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 20, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 18, 0, 16, 0, + 23, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 34, 0, 16, 0, + 23, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 23, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 20, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 23, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 23, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 23, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 23, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 34, 0, 16, 0, + 23, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 26, 0, 16, 0, 23, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 23, 0, 0, 0, 10, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 66, 0, 16, 0, + 23, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 42, 0, 16, 0, 23, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 18, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 23, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 23, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 48, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 6, 34, 48, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 40, 0, + 0, 5, 18, 0, 16, 0, + 24, 0, 0, 0, 58, 0, + 16, 0, 20, 0, 0, 0, + 40, 0, 0, 5, 226, 0, + 16, 0, 24, 0, 0, 0, + 6, 9, 16, 0, 23, 0, + 0, 0, 33, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 43, 0, 0, 5, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 13, 0, + 0, 0, 55, 0, 0, 15, + 114, 0, 16, 0, 23, 0, + 0, 0, 246, 15, 16, 0, + 19, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 128, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 64, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 40, 0, 0, 5, + 18, 0, 16, 0, 25, 0, + 0, 0, 58, 0, 16, 0, + 15, 0, 0, 0, 40, 0, + 0, 5, 34, 0, 16, 0, + 25, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 40, 0, 0, 5, 194, 0, + 16, 0, 25, 0, 0, 0, + 6, 4, 16, 0, 20, 0, + 0, 0, 33, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 43, 0, 0, 5, 130, 0, + 16, 0, 14, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 15, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 19, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 130, 0, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 58, 0, 16, 0, 18, 0, + 0, 0, 85, 0, 0, 8, + 130, 0, 16, 0, 18, 0, + 0, 0, 10, 144, 144, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 15, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 32, 0, 0, 7, + 130, 0, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 19, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 15, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 20, 0, 0, 0, + 70, 14, 16, 0, 24, 0, + 0, 0, 70, 14, 16, 0, + 20, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 50, 0, 16, 0, 20, 0, + 0, 0, 70, 0, 16, 0, + 20, 0, 0, 0, 70, 0, + 16, 0, 22, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 19, 0, 0, 0, + 26, 0, 16, 0, 20, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 19, 0, 0, 0, 42, 0, + 16, 0, 22, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 22, 0, 0, 0, + 58, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 33, 0, + 0, 7, 18, 0, 16, 0, + 20, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 19, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 34, 0, 0, 7, 34, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 13, 0, 0, 0, 43, 0, + 0, 5, 130, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 19, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 19, 0, 0, 0, + 58, 0, 16, 0, 19, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 14, 0, + 0, 7, 130, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 19, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 28, 0, 0, 5, + 130, 0, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 19, 0, 0, 0, + 26, 0, 16, 0, 23, 0, + 0, 0, 55, 0, 0, 10, + 130, 0, 16, 0, 19, 0, + 0, 0, 26, 0, 16, 0, + 20, 0, 0, 0, 58, 144, + 144, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 42, 0, + 16, 0, 23, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 19, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 19, 0, 0, 0, + 18, 0, 0, 1, 167, 0, + 0, 9, 242, 0, 16, 0, + 20, 0, 0, 0, 58, 0, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 20, 0, 0, 0, 70, 14, + 16, 0, 25, 0, 0, 0, + 70, 14, 16, 0, 20, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 50, 0, + 16, 0, 20, 0, 0, 0, + 70, 0, 16, 0, 20, 0, + 0, 0, 70, 0, 16, 0, + 21, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 20, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 35, 0, 0, 9, + 18, 0, 16, 0, 20, 0, + 0, 0, 42, 0, 16, 0, + 21, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 35, 0, 0, 9, + 18, 0, 16, 0, 20, 0, + 0, 0, 58, 0, 16, 0, + 21, 0, 0, 0, 58, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 33, 0, 0, 7, + 34, 0, 16, 0, 20, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 60, 0, 0, 7, 34, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 20, 0, 0, 0, 34, 0, + 0, 7, 66, 0, 16, 0, + 20, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 43, 0, 0, 5, + 18, 0, 16, 0, 20, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 20, 0, 0, 0, 10, 0, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 14, 0, 0, 7, + 18, 0, 16, 0, 20, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 58, 0, + 16, 0, 14, 0, 0, 0, + 28, 0, 0, 5, 18, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 30, 0, 0, 7, + 18, 0, 16, 0, 20, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 26, 0, + 16, 0, 23, 0, 0, 0, + 55, 0, 0, 10, 18, 0, + 16, 0, 20, 0, 0, 0, + 42, 0, 16, 0, 20, 0, + 0, 0, 58, 144, 144, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 42, 0, 16, 0, + 23, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 19, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 21, 0, + 0, 1, 30, 0, 0, 7, + 130, 0, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 10, 0, + 16, 0, 23, 0, 0, 0, + 30, 0, 0, 10, 18, 0, + 16, 0, 20, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 10, 144, 208, 128, + 65, 0, 0, 0, 64, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 41, 0, + 0, 7, 130, 0, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 54, 0, 0, 7, + 18, 0, 16, 0, 26, 0, + 0, 0, 10, 48, 32, 4, + 0, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 54, 0, 0, 8, 34, 0, + 16, 0, 26, 0, 0, 0, + 10, 48, 32, 6, 0, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 54, 0, 0, 8, + 66, 0, 16, 0, 26, 0, + 0, 0, 10, 48, 32, 6, + 0, 0, 0, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 54, 0, + 0, 8, 130, 0, 16, 0, + 26, 0, 0, 0, 10, 48, + 32, 6, 0, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 54, 0, 0, 7, 18, 0, + 16, 0, 27, 0, 0, 0, + 26, 48, 32, 4, 0, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 54, 0, + 0, 8, 34, 0, 16, 0, + 27, 0, 0, 0, 26, 48, + 32, 6, 0, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 54, 0, 0, 8, 66, 0, + 16, 0, 27, 0, 0, 0, + 26, 48, 32, 6, 0, 0, + 0, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 54, 0, 0, 8, + 130, 0, 16, 0, 27, 0, + 0, 0, 26, 48, 32, 6, + 0, 0, 0, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 38, 0, + 0, 10, 0, 208, 0, 0, + 242, 0, 16, 0, 27, 0, + 0, 0, 70, 14, 16, 0, + 27, 0, 0, 0, 6, 144, + 208, 0, 64, 0, 0, 0, + 58, 0, 16, 0, 19, 0, + 0, 0, 35, 0, 0, 9, + 242, 0, 16, 0, 20, 0, + 0, 0, 6, 0, 16, 0, + 20, 0, 0, 0, 70, 14, + 16, 0, 26, 0, 0, 0, + 70, 14, 16, 0, 27, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 20, 0, + 0, 0, 70, 14, 16, 0, + 20, 0, 0, 0, 2, 64, + 0, 0, 32, 0, 0, 0, + 32, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, + 85, 0, 0, 7, 242, 0, + 16, 0, 20, 0, 0, 0, + 134, 13, 16, 0, 20, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 55, 0, + 0, 9, 130, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 255, 0, + 0, 0, 58, 0, 16, 0, + 20, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 26, 0, 0, 0, 58, 0, + 16, 0, 15, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 79, 0, + 0, 7, 114, 0, 16, 0, + 27, 0, 0, 0, 134, 1, + 16, 0, 20, 0, 0, 0, + 70, 2, 16, 0, 26, 0, + 0, 0, 54, 0, 0, 5, + 82, 0, 16, 0, 28, 0, + 0, 0, 6, 1, 16, 0, + 26, 0, 0, 0, 54, 0, + 0, 5, 162, 0, 16, 0, + 28, 0, 0, 0, 6, 8, + 16, 0, 20, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 28, 0, 0, 0, + 6, 5, 16, 0, 27, 0, + 0, 0, 70, 14, 16, 0, + 28, 0, 0, 0, 22, 11, + 16, 0, 28, 0, 0, 0, + 54, 0, 0, 5, 82, 0, + 16, 0, 20, 0, 0, 0, + 166, 11, 16, 0, 26, 0, + 0, 0, 55, 0, 0, 9, + 50, 0, 16, 0, 20, 0, + 0, 0, 166, 10, 16, 0, + 27, 0, 0, 0, 70, 0, + 16, 0, 20, 0, 0, 0, + 22, 5, 16, 0, 20, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 20, 0, 0, 0, 58, 0, + 16, 0, 26, 0, 0, 0, + 55, 0, 0, 9, 146, 0, + 16, 0, 26, 0, 0, 0, + 246, 15, 16, 0, 18, 0, + 0, 0, 246, 11, 16, 0, + 20, 0, 0, 0, 166, 14, + 16, 0, 20, 0, 0, 0, + 40, 0, 0, 5, 50, 0, + 16, 0, 27, 0, 0, 0, + 214, 5, 16, 0, 28, 0, + 0, 0, 40, 0, 0, 5, + 66, 0, 16, 0, 27, 0, + 0, 0, 26, 0, 16, 0, + 20, 0, 0, 0, 40, 0, + 0, 5, 130, 0, 16, 0, + 27, 0, 0, 0, 10, 0, + 16, 0, 26, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 26, 0, 0, 0, + 134, 0, 16, 0, 28, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 26, 0, + 0, 0, 10, 0, 16, 0, + 20, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 20, 0, 0, 0, 70, 14, + 16, 0, 27, 0, 0, 0, + 70, 14, 16, 0, 26, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 50, 0, + 16, 0, 20, 0, 0, 0, + 70, 0, 16, 0, 20, 0, + 0, 0, 70, 0, 16, 0, + 20, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 18, 0, 0, 0, 26, 0, + 16, 0, 20, 0, 0, 0, + 10, 0, 16, 0, 20, 0, + 0, 0, 35, 0, 0, 9, + 130, 0, 16, 0, 18, 0, + 0, 0, 42, 0, 16, 0, + 20, 0, 0, 0, 42, 0, + 16, 0, 20, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 86, 0, 0, 5, + 130, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 86, 0, + 0, 5, 130, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 20, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 19, 0, 0, 0, + 58, 0, 16, 0, 19, 0, + 0, 0, 58, 0, 16, 0, + 19, 0, 0, 0, 50, 0, + 0, 10, 130, 0, 16, 0, + 18, 0, 0, 0, 58, 0, + 16, 0, 19, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 18, 0, + 0, 0, 28, 0, 0, 5, + 130, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 18, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 19, 0, 0, 0, 58, 0, + 16, 0, 18, 0, 0, 0, + 26, 0, 16, 0, 19, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 22, 0, 0, 1, 79, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 19, 0, 0, 0, + 26, 0, 16, 0, 18, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 50, 0, 16, 0, + 18, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 19, 0, + 0, 0, 70, 0, 16, 0, + 18, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 19, 0, 0, 0, 10, 0, + 16, 0, 19, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 18, 0, 0, 0, 22, 0, + 0, 1, 54, 0, 0, 6, + 18, 0, 16, 0, 18, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 4, + 66, 0, 16, 0, 18, 0, + 0, 0, 10, 64, 2, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 22, 6, 16, 0, 18, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 190, 24, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 18, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 134, 3, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 134, 3, 16, 0, 3, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 8, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 134, 3, 16, 0, 3, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 4, 3, 58, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 134, 3, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 79, 0, 0, 9, 98, 0, + 16, 0, 0, 0, 0, 0, + 6, 64, 2, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 134, 3, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 6, 249, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 32, 0, 0, 0, + 6, 240, 17, 0, 0, 0, + 0, 0, 79, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 168, 0, 0, 8, 114, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 134, 3, 16, 0, 2, 0, + 0, 0, 168, 0, 0, 8, + 18, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 167, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 6, 112, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 79, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 26, 0, 16, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 242, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 130, 0, 16, 0, + 1, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 32, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 167, 0, + 0, 9, 242, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 21, 0, + 0, 1, 168, 0, 0, 9, + 242, 224, 17, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 62, 0, 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode137CS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode137CS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..187ad5b2d7fb687de7d458f6cdb9c87dc9ea632d Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode137CS.pdb differ diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode456CS.inc b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode456CS.inc new file mode 100644 index 0000000000000000000000000000000000000000..d828ae1e31427c0b532cd9395bf82122d310981d --- /dev/null +++ b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode456CS.inc @@ -0,0 +1,3026 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_4_0 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { 0, 0, 0, 0}, + { 0, 4, 0, 0}, + { 0, 9, 0, 0}, + { 1, 13, 0, 0}, + { 1, 17, 0, 0}, + { 1, 21, 0, 0}, + { 1, 26, 0, 0}, + { 2, 30, 0, 0}, + { 2, 34, 0, 0}, + { 2, 38, 0, 0}, + { 2, 43, 0, 0}, + { 2, 47, 0, 0}, + { 3, 51, 0, 0}, + { 3, 55, 0, 0}, + { 3, 60, 0, 0}, + { 3, 64, 0, 0}, + { 4, 0, 0, 0}, + { 4, 9, 0, 0}, + { 4, 18, 0, 0}, + { 4, 27, 0, 0}, + { 5, 37, 0, 0}, + { 5, 46, 0, 0}, + { 5, 55, 0, 0}, + { 5, 64, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 8, 21, 0, 0}, + { 8, 43, 0, 0}, + { 8, 64, 0, 0}, + { 8, 0, 0, 0}, + { 9, 0, 0, 0}, + { 9, 0, 0, 0}, + { 9, 0, 0, 0}, + { 9, 0, 0, 0}, + { 10, 0, 0, 0}, + { 10, 0, 0, 0}, + { 10, 0, 0, 0}, + { 10, 0, 0, 0}, + { 10, 0, 0, 0}, + { 11, 0, 0, 0}, + { 11, 0, 0, 0}, + { 11, 0, 0, 0}, + { 11, 0, 0, 0}, + { 12, 0, 0, 0}, + { 12, 0, 0, 0}, + { 12, 0, 0, 0}, + { 12, 0, 0, 0}, + { 13, 0, 0, 0}, + { 13, 0, 0, 0}, + { 13, 0, 0, 0}, + { 13, 0, 0, 0}, + { 14, 0, 0, 0}, + { 14, 0, 0, 0}, + { 14, 0, 0, 0}, + { 14, 0, 0, 0}, + { 15, 0, 0, 0}, + { 15, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 4, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 5, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 6, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 0, 0, 0}, + { 7, 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, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 2, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0}, + { 3, 0, 0, 0} } +dcl_constantbuffer CB0[2], immediateIndexed +dcl_resource_texture2d (float,float,float,float) t0 +dcl_uav_structured u0, 16 +dcl_input vThreadIDInGroupFlattened +dcl_input vThreadGroupID.x +dcl_temps 19 +dcl_tgsm_structured g0, 100, 64 +dcl_thread_group 64, 1, 1 +ushr r0.x, vThreadIDInGroupFlattened.x, l(4) +ishl r0.y, vThreadGroupID.x, l(2) +iadd r0.y, r0.y, cb0[1].x +iadd r0.x, r0.x, r0.y +uge r0.y, r0.x, cb0[1].y +if_nz r0.y + ret +endif +and r0.y, vThreadIDInGroupFlattened.x, l(48) +iadd r0.z, -r0.y, vThreadIDInGroupFlattened.x +ult r1.xyzw, r0.zzzz, l(16, 8, 4, 2) +if_nz r1.x + udiv r0.w, null, r0.x, cb0[0].y + imad r2.x, -r0.w, cb0[0].y, r0.x + ishl r2.x, r2.x, l(2) + ishl r0.w, r0.w, l(2) + and r2.y, r0.z, l(3) + iadd r2.x, r2.y, r2.x + ushr r3.x, r0.z, l(2) + iadd r2.y, r0.w, r3.x + mov r2.zw, l(0,0,0,0) + ld r2.xyzw, r2.xyzw, t0.xyzw + mul r2.xyzw, r2.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000) + ftou r2.xyzw, r2.xyzw + umin r2.xyzw, r2.xyzw, l(255, 255, 255, 255) + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(0), r2.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r2.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r2.xyzw +endif +if_nz r1.y + ld_structured r2.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r0.w, vThreadIDInGroupFlattened.x, l(8) + ld_structured r4.xyzw, r0.w, l(36), g0.xyzw + ld_structured r5.xyzw, r0.w, l(52), g0.xyzw + umin r2.xyzw, r2.xyzw, r4.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r2.xyzw + umax r2.xyzw, r3.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r2.xyzw +endif +if_nz r1.z + ld_structured r2.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r0.w, vThreadIDInGroupFlattened.x, l(4) + ld_structured r4.xyzw, r0.w, l(36), g0.xyzw + ld_structured r5.xyzw, r0.w, l(52), g0.xyzw + umin r2.xyzw, r2.xyzw, r4.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r2.xyzw + umax r2.xyzw, r3.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r2.xyzw +endif +if_nz r1.w + ld_structured r2.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r0.w, vThreadIDInGroupFlattened.x, l(2) + ld_structured r4.xyzw, r0.w, l(36), g0.xyzw + ld_structured r5.xyzw, r0.w, l(52), g0.xyzw + umin r2.xyzw, r2.xyzw, r4.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r2.xyzw + umax r2.xyzw, r3.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r2.xyzw +endif +ult r2.xy, r0.zzzz, l(1, 12, 0, 0) +if_nz r2.x + ld_structured r3.xyzw, vThreadIDInGroupFlattened.x, l(36), g0.xyzw + ld_structured r4.xyzw, vThreadIDInGroupFlattened.x, l(52), g0.xyzw + iadd r0.w, vThreadIDInGroupFlattened.x, l(1) + ld_structured r5.xyzw, r0.w, l(36), g0.xyzw + ld_structured r6.xyzw, r0.w, l(52), g0.xyzw + umin r3.xyzw, r3.xyzw, r5.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(36), r3.xyzw + umax r3.xyzw, r4.xyzw, r6.xyzw + store_structured g0.xyzw, vThreadIDInGroupFlattened.x, l(52), r3.xyzw +endif +ld_structured r3.xyzw, r0.y, l(0), g0.xyzw +ld_structured r4.xyzw, r0.y, l(36), g0.xyzw +ld_structured r5.xyzw, r0.y, l(52), g0.xyzw +and r0.w, r0.z, l(1) +movc r6.xyz, r0.wwww, l(1,1,2,0), l(0,2,1,0) +movc r6.xyz, r1.yyyy, r6.xyzx, l(0,2,2,0) +if_nz r2.y + ieq r7.xyzw, r0.zzzz, l(8, 9, 10, 11) + ult r0.w, r0.z, l(6) + or r0.w, r7.z, r0.w + or r2.yzw, r1.wwzy, r7.xxyw + mov r7.y, r4.z + mov r7.w, r5.z + mov r7.x, l(3) + mov r8.x, r4.w + mov r8.y, r5.w + mov r8.z, l(0) + movc r9.xyz, r2.wwww, r7.ywxy, r8.xyzx + movc r10.yw, r2.wwww, r8.xxxy, r7.yyyw + mov r11.x, r4.y + mov r11.y, r5.y + mov r11.z, l(2) + movc r9.xyz, r0.wwww, r11.xyzx, r9.xyzx + mov r7.xz, r8.xxyx + mov r10.xz, r11.xxyx + movc r7.xyzw, r0.wwww, r7.xzwy, r10.xzwy + mov r10.x, r4.x + mov r10.yz, r7.xxwx + movc r11.xyz, r2.zzzz, r4.wyzw, r10.xyzx + mov r10.y, r5.x + mov r10.z, l(1) + movc r9.xyz, r2.zzzz, r10.xyzx, r9.xyzx + mov r7.x, r10.y + movc r7.xyz, r2.zzzz, r5.wyzw, r7.xyzx + movc r10.xyz, r2.yyyy, r4.xyzx, r11.xyzx + movc r7.xyz, r2.yyyy, r5.xyzx, r7.xyzx + movc r2.yzw, r2.yyyy, r8.xxyz, r9.xxyz + if_nz r1.y + iadd r8.xyz, r10.xyzx, l(4, 4, 4, 0) + umin r8.xyz, r8.xyzx, l(255, 255, 255, 0) + iadd r9.xy, r2.yzyy, l(2, 2, 0, 0) + umin r9.xy, r9.xyxx, l(255, 255, 0, 0) + and r11.xyz, r8.xyzx, l(248, 248, 248, 0) + ushr r8.xyz, r8.xyzx, l(5) + iadd r8.xyz, r8.xyzx, r11.xyzx + and r9.zw, r9.xxxy, l(0, 0, 252, 252) + ushr r9.xy, r9.xyxx, l(6) + iadd r11.xyz, r7.xyzx, l(4, 4, 4, 0) + umin r11.xyz, r11.xyzx, l(255, 255, 255, 0) + and r12.xyz, r11.xyzx, l(248, 248, 248, 0) + ushr r11.xyz, r11.xyzx, l(5) + iadd r11.xyz, r11.xyzx, r12.xyzx + iadd r9.xy, r9.xyxx, r9.zwzz + mov r11.w, r9.y + mov r12.y, l(4) + else + iadd r10.xyz, r10.xyzx, l(1, 1, 1, 0) + umin r10.xyz, r10.xyzx, l(255, 255, 255, 0) + and r13.xyz, r10.xyzx, l(254, 254, 254, 0) + ushr r10.xyz, r10.xyzx, l(7) + iadd r8.xyz, r10.xyzx, r13.xyzx + iadd r7.xyz, r7.xyzx, l(1, 1, 1, 0) + umin r7.xyz, r7.xyzx, l(255, 255, 255, 0) + and r10.xyz, r7.xyzx, l(254, 254, 254, 0) + ushr r7.xyz, r7.xyzx, l(7) + iadd r11.xyz, r7.xyzx, r10.xyzx + mov r9.x, r2.y + mov r11.w, r2.z + mov r12.y, l(5) + endif + ieq r7.xyz, r2.wwww, l(1, 2, 3, 0) + movc r10.zw, r7.zzzz, r3.wwwz, r3.zzzw + mov r10.xy, r3.xyxx + movc r10.yzw, r7.yyyy, r3.wwzy, r10.yyzw + movc r10.xyzw, r7.xxxx, r3.wyzx, r10.xyzw + ineg r13.xyz, r8.xyzx + ineg r13.w, r9.x + iadd r14.xyzw, r11.xyzw, r13.xyzw + imul null, r15.xyz, r14.xywx, r14.xywx + iadd r0.w, r15.y, r15.x + imad r0.w, r14.z, r14.z, r0.w + iadd r13.xyzw, r10.xyzw, r13.xyzw + imul null, r13.xyw, r13.xyxw, r13.xyxw + iadd r2.y, r13.y, r13.x + imad r2.y, r13.z, r13.z, r2.y + iadd r10.xyzw, -r11.xyzw, r10.xyzw + imul null, r10.xyw, r10.xyxw, r10.xyxw + iadd r2.z, r10.y, r10.x + imad r2.z, r10.z, r10.z, r2.z + ilt r2.y, r2.z, r2.y + ineg r16.xyzw, r14.xyzw + movc r10.xyz, r2.yyyy, r11.xyzx, r8.xyzx + movc r8.xyz, r2.yyyy, r8.xyzx, r11.xyzx + movc r11.xyz, r2.yyyy, r16.xyzx, r14.xyzx + ilt r2.y, r10.w, r13.w + mov r9.y, r11.w + mov r9.z, r16.w + mov r9.w, r14.w + movc r9.xyz, r2.yyyy, r9.yxzy, r9.xywx + ige r2.y, l(0), r0.w + itof r2.z, r0.w + ishl r12.zw, r6.yyyz, l(6) + ishl r6.yz, r6.yyzy, l(4) + iadd r13.xy, r12.zwzz, l(11, 11, 0, 0) + ige r7.w, l(0), r15.z + itof r8.w, r15.z + udiv null, r13.xy, r13.xyxx, l(68, 68, 0, 0) + mov r13.zw, l(0,0,0,0) + loop + uge r9.w, r13.w, l(16) + breakc_nz r9.w + iadd r9.w, r0.y, r13.w + ld_structured r14.xyzw, r9.w, l(0), g0.xyzw + movc r16.zw, r7.zzzz, r14.wwwz, r14.zzzw + mov r16.xy, r14.xyxx + movc r16.yzw, r7.yyyy, r14.wwzy, r16.yyzw + movc r14.xyzw, r7.xxxx, r14.wyzx, r16.xyzw + iadd r15.xyw, -r10.xyxz, r14.xyxz + imul null, r15.xy, r11.xyxx, r15.xyxx + iadd r9.w, r15.y, r15.x + imad r9.w, r11.z, r15.w, r9.w + ige r10.w, l(0), r9.w + or r10.w, r2.y, r10.w + ilt r11.w, r9.w, r0.w + itof r9.w, r9.w + mul r9.w, r9.w, l(63.499989) + div r9.w, r9.w, r2.z + ftou r9.w, r9.w + iadd r9.w, r9.w, r12.z + movc r9.w, r11.w, icb[r9.w + 0].x, r13.x + movc r9.w, r10.w, l(0), r9.w + iadd r10.w, -r9.x, r14.w + imul null, r10.w, r9.z, r10.w + ige r11.w, l(0), r10.w + or r11.w, r7.w, r11.w + ilt r15.x, r10.w, r15.z + itof r10.w, r10.w + mul r10.w, r10.w, l(63.499989) + div r10.w, r10.w, r8.w + ftou r10.w, r10.w + iadd r10.w, r10.w, r12.w + movc r10.w, r15.x, icb[r10.w + 0].x, r13.y + movc r10.w, r11.w, l(0), r10.w + iadd r9.w, r6.y, r9.w + iadd r11.w, l(64), -icb[r9.w + 0].y + imul null, r15.xyw, r8.xyxz, icb[r9.w + 0].yyyy + imad r15.xyw, r11.wwww, r10.xyxz, r15.xyxw + iadd r15.xyw, r15.xyxw, l(32, 32, 0, 32) + ushr r16.xyw, r15.xyxw, l(6) + iadd r9.w, r6.z, r10.w + iadd r10.w, l(64), -icb[r9.w + 0].y + imul null, r9.w, r9.y, icb[r9.w + 0].y + imad r9.w, r10.w, r9.x, r9.w + iadd r9.w, r9.w, l(32) + ushr r15.y, r9.w, l(6) + ult r17.xyz, r16.xywx, r14.xyzx + mov r16.z, r14.x + movc r17.xw, r17.xxxx, r16.zzzx, r16.xxxz + mov r16.xz, r14.yyzy + movc r16.xyzw, r17.yyzz, r16.xyzw, r16.yxwz + ult r9.w, r15.y, r14.w + mov r15.x, r14.w + movc r14.xy, r9.wwww, r15.xyxx, r15.yxyy + ineg r18.w, r17.w + ineg r18.yz, r16.yywy + ineg r18.x, r14.y + mov r14.w, r17.x + mov r14.yz, r16.xxzx + iadd r14.xyzw, r18.xyzw, r14.xyzw + movc r16.zw, r7.zzzz, r14.xxxz, r14.zzzx + mov r16.xy, r14.wyww + movc r16.yzw, r7.yyyy, r14.xxzy, r16.yyzw + movc r14.xyzw, r7.xxxx, r14.xyzw, r16.xyzw + imul null, r14.xy, r14.xyxx, r14.xyxx + iadd r9.w, r14.y, r14.x + imad r9.w, r14.z, r14.z, r9.w + utof r9.w, r9.w + utof r10.w, r14.w + mul r10.w, r10.w, r10.w + mad r9.w, r10.w, cb0[1].z, r9.w + ftou r9.w, r9.w + iadd r13.z, r9.w, r13.z + iadd r13.w, r13.w, l(1) + endloop + mov r12.x, r13.z + mov r6.w, r2.w +else + if_nz r1.x + iadd r7.x, r0.z, l(-12) + ushr r7.y, r7.x, l(1) + and r0.zw, r7.xxxy, l(0, 0, 1, 1) + and r4.xyzw, r4.xyzw, l(-2, -2, -2, -2) + iadd r4.xyzw, r0.zzzz, r4.xyzw + and r5.xyzw, r5.xyzw, l(-2, -2, -2, -2) + iadd r5.xyzw, r0.wwww, r5.xyzw + iadd r8.xyzw, -r4.xyzw, r5.xyzw + imul null, r0.zw, r8.xxxy, r8.xxxy + iadd r0.z, r0.w, r0.z + imad r0.z, r8.z, r8.z, r0.z + imad r0.z, r8.w, r8.w, r0.z + iadd r3.xyzw, r3.xyzw, -r4.xyzw + imul null, r2.yz, r3.xxyx, r8.xxyx + iadd r0.w, r2.z, r2.y + imad r0.w, r8.z, r3.z, r0.w + imad r0.w, r8.w, r3.w, r0.w + ilt r1.x, l(0), r0.z + ige r2.y, r0.w, l(0) + and r1.x, r1.x, r2.y + itof r0.w, r0.w + mul r0.w, r0.w, l(63.499989) + ftou r0.w, r0.w + ishl r2.y, r0.z, l(5) + ult r0.w, r2.y, r0.w + and r0.w, r0.w, r1.x + ineg r3.xyzw, r8.xyzw + movc r9.xyzw, r0.wwww, r5.xyzw, r4.xyzw + movc r4.xyzw, r0.wwww, r4.xyzw, r5.xyzw + movc r3.xyzw, r0.wwww, r3.xyzw, r8.xyzw + ige r0.w, l(0), r0.z + itof r1.x, r0.z + mov r12.xy, l(0,0,0,0) + loop + uge r2.y, r12.y, l(16) + breakc_nz r2.y + iadd r2.y, r0.y, r12.y + ld_structured r5.xyzw, r2.y, l(0), g0.xyzw + iadd r8.xyzw, -r9.xyzw, r5.xyzw + imul null, r2.yz, r3.xxyx, r8.xxyx + iadd r2.y, r2.z, r2.y + imad r2.y, r3.z, r8.z, r2.y + imad r2.y, r3.w, r8.w, r2.y + ige r2.z, l(0), r2.y + or r2.z, r0.w, r2.z + ilt r2.w, r2.y, r0.z + itof r2.y, r2.y + mul r2.y, r2.y, l(63.499989) + div r2.y, r2.y, r1.x + ftou r2.y, r2.y + movc r2.y, r2.w, icb[r2.y + 0].x, l(15) + movc r2.y, r2.z, l(0), r2.y + iadd r2.z, l(64), -icb[r2.y + 0].y + imul null, r8.xyzw, r4.xyzw, icb[r2.y + 0].yyyy + imad r8.xyzw, r2.zzzz, r9.xyzw, r8.xyzw + iadd r8.xyzw, r8.xyzw, l(32, 32, 32, 32) + ushr r8.xyzw, r8.xzyw, l(6) + ult r10.xyzw, r8.xzyw, r5.xyzw + mov r11.xz, r5.xxyx + mov r11.yw, r8.xxxz + movc r11.xyzw, r10.xxyy, r11.xyzw, r11.yxwz + mov r8.xz, r5.zzwz + movc r5.xyzw, r10.zwzw, r8.ywxz, r8.xzyw + ineg r8.xy, r11.ywyy + ineg r8.zw, r5.xxxy + mov r5.xy, r11.xzxx + iadd r5.xyzw, r8.xyzw, r5.xyzw + imul null, r2.yz, r5.xxyx, r5.xxyx + iadd r2.y, r2.z, r2.y + imad r2.y, r5.z, r5.z, r2.y + utof r2.y, r2.y + utof r2.z, r5.w + mul r2.z, r2.z, r2.z + mad r2.y, r2.z, cb0[1].z, r2.y + ftou r2.y, r2.y + iadd r12.x, r2.y, r12.x + iadd r12.y, r12.y, l(1) + endloop + mov r12.y, l(6) + mov r6.w, r7.x + else + mov r12.xy, l(-1,0,0,0) + mov r6.w, l(0) + endif +endif +store_structured g0.xy, vThreadIDInGroupFlattened.x, l(16), r12.xyxx +store_structured g0.xy, vThreadIDInGroupFlattened.x, l(28), r6.xwxx +if_nz r1.y + iadd r0.y, vThreadIDInGroupFlattened.x, l(8) + ld_structured r3.yz, r0.y, l(16), g0.xxyx + ld_structured r4.xy, r0.y, l(28), g0.xyxx + ult r0.z, r3.y, r12.x + if_nz r0.z + ld_structured r3.x, r0.y, l(16), g0.xxxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(16), r3.xzxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(28), r4.xyxx + endif +endif +if_nz r1.z + ld_structured r3.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(4) + ld_structured r4.yz, r0.y, l(16), g0.xxyx + ld_structured r5.xy, r0.y, l(28), g0.xyxx + ult r0.z, r4.y, r3.x + if_nz r0.z + ld_structured r4.x, r0.y, l(16), g0.xxxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(16), r4.xzxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(28), r5.xyxx + endif +endif +if_nz r1.w + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(2) + ld_structured r3.yz, r0.y, l(16), g0.xxyx + ld_structured r4.xy, r0.y, l(28), g0.xyxx + ult r0.z, r3.y, r1.x + if_nz r0.z + ld_structured r3.x, r0.y, l(16), g0.xxxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(16), r3.xzxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(28), r4.xyxx + endif +endif +if_nz r2.x + ld_structured r1.x, vThreadIDInGroupFlattened.x, l(16), g0.xxxx + iadd r0.y, vThreadIDInGroupFlattened.x, l(1) + ld_structured r2.yz, r0.y, l(16), g0.xxyx + ld_structured r3.xy, r0.y, l(28), g0.xyxx + ult r0.z, r2.y, r1.x + if_nz r0.z + ld_structured r2.x, r0.y, l(16), g0.xxxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(16), r2.xzxx + store_structured g0.xy, vThreadIDInGroupFlattened.x, l(28), r3.xyxx + endif + ld_structured r1.xw, vThreadIDInGroupFlattened.x, l(28), g0.xxxy + ishl r0.y, r1.x, l(31) + ld_structured r1.xy, vThreadIDInGroupFlattened.x, l(16), g0.xyxx + or r1.y, r0.y, r1.y + mov r1.z, l(0) + store_structured u0.xyzw, r0.x, l(0), r1.xyzw +endif +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BC7Encode_TryMode456CS[] = +{ + 68, 88, 66, 67, 193, 29, + 43, 212, 231, 175, 144, 60, + 211, 12, 231, 93, 197, 161, + 15, 183, 1, 0, 0, 0, + 56, 56, 0, 0, 3, 0, + 0, 0, 44, 0, 0, 0, + 60, 0, 0, 0, 76, 0, + 0, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 228, 55, 0, 0, + 64, 0, 5, 0, 249, 13, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 2, 3, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 30, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 43, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 47, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 64, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 27, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 46, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 64, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 21, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 43, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 64, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 15, 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, + 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, 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 7, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 158, 0, + 0, 4, 0, 224, 17, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 95, 0, 0, 2, + 0, 64, 2, 0, 95, 0, + 0, 2, 18, 16, 2, 0, + 104, 0, 0, 2, 19, 0, + 0, 0, 160, 0, 0, 5, + 0, 240, 17, 0, 0, 0, + 0, 0, 100, 0, 0, 0, + 64, 0, 0, 0, 155, 0, + 0, 4, 64, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 85, 0, 0, 6, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 41, 0, 0, 6, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 30, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 80, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 21, 0, 0, 1, + 1, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 48, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 79, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 16, 0, + 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 78, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 0, 208, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 11, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 41, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 7, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 126, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 127, 67, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 127, 67, 28, 0, 0, 5, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 84, 0, + 0, 10, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 2, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 3, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 30, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 8, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 242, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 84, 0, + 0, 7, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 83, 0, + 0, 7, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 168, 0, 0, 8, + 242, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 52, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 1, 0, + 0, 0, 167, 0, 0, 8, + 242, 0, 16, 0, 2, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 36, 0, + 0, 0, 70, 254, 17, 0, + 0, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 84, 0, 0, 7, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 83, 0, 0, 7, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 168, 0, + 0, 8, 242, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 58, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 2, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 3, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 84, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 79, 0, 0, 10, 50, 0, + 16, 0, 2, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 242, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 8, 242, 0, + 16, 0, 4, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 30, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 167, 0, 0, 9, + 242, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 254, 17, 0, 0, 0, + 0, 0, 84, 0, 0, 7, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 36, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 83, 0, 0, 7, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 168, 0, 0, 8, 242, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 52, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 9, 242, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 36, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 52, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 15, 114, 0, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 12, 114, 0, 16, 0, + 6, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 32, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 8, 0, + 0, 0, 9, 0, 0, 0, + 10, 0, 0, 0, 11, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 60, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 226, 0, 16, 0, + 2, 0, 0, 0, 246, 6, + 16, 0, 1, 0, 0, 0, + 6, 13, 16, 0, 7, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 7, 0, 0, 0, + 1, 64, 0, 0, 3, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 9, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 214, 4, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 55, 0, 0, 9, + 162, 0, 16, 0, 10, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 6, 4, + 16, 0, 8, 0, 0, 0, + 86, 13, 16, 0, 7, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 9, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 54, 0, 0, 5, + 82, 0, 16, 0, 7, 0, + 0, 0, 6, 1, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 5, 82, 0, 16, 0, + 10, 0, 0, 0, 6, 1, + 16, 0, 11, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 7, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 134, 7, 16, 0, + 7, 0, 0, 0, 134, 7, + 16, 0, 10, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 10, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 5, + 98, 0, 16, 0, 10, 0, + 0, 0, 6, 3, 16, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 118, 14, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 9, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 7, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 166, 10, + 16, 0, 2, 0, 0, 0, + 118, 14, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 7, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 55, 0, + 0, 9, 226, 0, 16, 0, + 2, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 6, 9, 16, 0, 8, 0, + 0, 0, 6, 9, 16, 0, + 9, 0, 0, 0, 31, 0, + 4, 3, 26, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 9, 0, 0, 0, + 150, 5, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 50, 0, 16, 0, + 9, 0, 0, 0, 70, 0, + 16, 0, 9, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 248, 0, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 1, 0, 0, 10, + 194, 0, 16, 0, 9, 0, + 0, 0, 6, 4, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 252, 0, + 0, 0, 252, 0, 0, 0, + 85, 0, 0, 7, 50, 0, + 16, 0, 9, 0, 0, 0, + 70, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 30, 0, + 0, 10, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 84, 0, 0, 10, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 2, 64, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 2, 64, 0, 0, + 248, 0, 0, 0, 248, 0, + 0, 0, 248, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 7, 114, 0, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 5, 0, + 0, 0, 30, 0, 0, 7, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 30, 0, 0, 7, 50, 0, + 16, 0, 9, 0, 0, 0, + 70, 0, 16, 0, 9, 0, + 0, 0, 230, 10, 16, 0, + 9, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 18, 0, 0, 1, + 30, 0, 0, 10, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 2, 64, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 84, 0, + 0, 10, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 2, 64, + 0, 0, 254, 0, 0, 0, + 254, 0, 0, 0, 254, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 114, 0, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 7, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 30, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 84, 0, 0, 10, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 254, 0, + 0, 0, 254, 0, 0, 0, + 254, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 7, 0, 0, 0, + 30, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 9, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 32, 0, 0, 10, + 114, 0, 16, 0, 7, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 194, 0, + 16, 0, 10, 0, 0, 0, + 166, 10, 16, 0, 7, 0, + 0, 0, 246, 11, 16, 0, + 3, 0, 0, 0, 166, 14, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 10, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 55, 0, 0, 9, + 226, 0, 16, 0, 10, 0, + 0, 0, 86, 5, 16, 0, + 7, 0, 0, 0, 246, 6, + 16, 0, 3, 0, 0, 0, + 86, 14, 16, 0, 10, 0, + 0, 0, 55, 0, 0, 9, + 242, 0, 16, 0, 10, 0, + 0, 0, 6, 0, 16, 0, + 7, 0, 0, 0, 118, 2, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 10, 0, + 0, 0, 40, 0, 0, 5, + 114, 0, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 40, 0, + 0, 5, 130, 0, 16, 0, + 13, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 14, 0, 0, 0, + 70, 14, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 13, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 114, 0, 16, 0, 15, 0, + 0, 0, 70, 3, 16, 0, + 14, 0, 0, 0, 70, 3, + 16, 0, 14, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 15, 0, + 0, 0, 10, 0, 16, 0, + 15, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 14, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 13, 0, 0, 0, 70, 14, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 13, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 178, 0, + 16, 0, 13, 0, 0, 0, + 70, 12, 16, 0, 13, 0, + 0, 0, 70, 12, 16, 0, + 13, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 13, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 8, + 242, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 178, 0, 16, 0, 10, 0, + 0, 0, 70, 12, 16, 0, + 10, 0, 0, 0, 70, 12, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 10, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 34, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 40, 0, 0, 5, + 242, 0, 16, 0, 16, 0, + 0, 0, 70, 14, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 10, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 8, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 55, 0, + 0, 9, 114, 0, 16, 0, + 11, 0, 0, 0, 86, 5, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 34, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 13, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 16, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 114, 0, 16, 0, 9, 0, + 0, 0, 86, 5, 16, 0, + 2, 0, 0, 0, 22, 6, + 16, 0, 9, 0, 0, 0, + 70, 3, 16, 0, 9, 0, + 0, 0, 33, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 43, 0, 0, 5, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 194, 0, 16, 0, 12, 0, + 0, 0, 86, 9, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 41, 0, 0, 7, 98, 0, + 16, 0, 6, 0, 0, 0, + 86, 6, 16, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 13, 0, 0, 0, 230, 10, + 16, 0, 12, 0, 0, 0, + 2, 64, 0, 0, 11, 0, + 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 15, 0, 0, 0, + 43, 0, 0, 5, 130, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 15, 0, + 0, 0, 78, 0, 0, 11, + 0, 208, 0, 0, 50, 0, + 16, 0, 13, 0, 0, 0, + 70, 0, 16, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 68, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 13, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 58, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 14, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 55, 0, 0, 9, 194, 0, + 16, 0, 16, 0, 0, 0, + 166, 10, 16, 0, 7, 0, + 0, 0, 246, 11, 16, 0, + 14, 0, 0, 0, 166, 14, + 16, 0, 14, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 16, 0, 0, 0, + 70, 0, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 226, 0, 16, 0, 16, 0, + 0, 0, 86, 5, 16, 0, + 7, 0, 0, 0, 246, 6, + 16, 0, 14, 0, 0, 0, + 86, 14, 16, 0, 16, 0, + 0, 0, 55, 0, 0, 9, + 242, 0, 16, 0, 14, 0, + 0, 0, 6, 0, 16, 0, + 7, 0, 0, 0, 118, 2, + 16, 0, 14, 0, 0, 0, + 70, 14, 16, 0, 16, 0, + 0, 0, 30, 0, 0, 8, + 178, 0, 16, 0, 15, 0, + 0, 0, 70, 8, 16, 128, + 65, 0, 0, 0, 10, 0, + 0, 0, 70, 8, 16, 0, + 14, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 50, 0, 16, 0, 15, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 70, 0, + 16, 0, 15, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 15, 0, + 0, 0, 10, 0, 16, 0, + 15, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 33, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 34, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 43, 0, + 0, 5, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 14, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 28, 0, 0, 5, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 55, 0, 0, 10, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 10, 144, + 144, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 10, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 130, 0, + 16, 0, 10, 0, 0, 0, + 42, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 33, 0, + 0, 7, 130, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 60, 0, 0, 7, + 130, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 34, 0, 0, 7, 18, 0, + 16, 0, 15, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 42, 0, 16, 0, + 15, 0, 0, 0, 43, 0, + 0, 5, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 253, 255, 125, 66, 14, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 28, 0, 0, 5, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 55, 0, 0, 10, + 130, 0, 16, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 15, 0, 0, 0, 10, 144, + 144, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 55, 0, 0, 9, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 9, 130, 0, 16, 0, + 11, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 26, 144, 144, 128, 65, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 38, 0, + 0, 9, 0, 208, 0, 0, + 178, 0, 16, 0, 15, 0, + 0, 0, 70, 8, 16, 0, + 8, 0, 0, 0, 86, 149, + 144, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 35, 0, + 0, 9, 178, 0, 16, 0, + 15, 0, 0, 0, 246, 15, + 16, 0, 11, 0, 0, 0, + 70, 8, 16, 0, 10, 0, + 0, 0, 70, 12, 16, 0, + 15, 0, 0, 0, 30, 0, + 0, 10, 178, 0, 16, 0, + 15, 0, 0, 0, 70, 12, + 16, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 32, 0, + 0, 0, 85, 0, 0, 7, + 178, 0, 16, 0, 16, 0, + 0, 0, 70, 12, 16, 0, + 15, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 30, 0, + 0, 9, 130, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 64, 0, 0, 0, + 26, 144, 144, 128, 65, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 38, 0, + 0, 9, 0, 208, 0, 0, + 130, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 9, 0, 0, 0, 26, 144, + 144, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 35, 0, + 0, 9, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 10, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 32, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 6, 0, 0, 0, + 79, 0, 0, 7, 114, 0, + 16, 0, 17, 0, 0, 0, + 70, 3, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 14, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 16, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 55, 0, 0, 9, 146, 0, + 16, 0, 17, 0, 0, 0, + 6, 0, 16, 0, 17, 0, + 0, 0, 166, 2, 16, 0, + 16, 0, 0, 0, 6, 8, + 16, 0, 16, 0, 0, 0, + 54, 0, 0, 5, 82, 0, + 16, 0, 16, 0, 0, 0, + 86, 6, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 242, 0, 16, 0, 16, 0, + 0, 0, 86, 10, 16, 0, + 17, 0, 0, 0, 70, 14, + 16, 0, 16, 0, 0, 0, + 22, 11, 16, 0, 16, 0, + 0, 0, 79, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 15, 0, 0, 0, 58, 0, + 16, 0, 14, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 15, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 55, 0, 0, 9, + 50, 0, 16, 0, 14, 0, + 0, 0, 246, 15, 16, 0, + 9, 0, 0, 0, 70, 0, + 16, 0, 15, 0, 0, 0, + 22, 5, 16, 0, 15, 0, + 0, 0, 40, 0, 0, 5, + 130, 0, 16, 0, 18, 0, + 0, 0, 58, 0, 16, 0, + 17, 0, 0, 0, 40, 0, + 0, 5, 98, 0, 16, 0, + 18, 0, 0, 0, 86, 7, + 16, 0, 16, 0, 0, 0, + 40, 0, 0, 5, 18, 0, + 16, 0, 18, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 14, 0, + 0, 0, 10, 0, 16, 0, + 17, 0, 0, 0, 54, 0, + 0, 5, 98, 0, 16, 0, + 14, 0, 0, 0, 6, 2, + 16, 0, 16, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 14, 0, 0, 0, + 70, 14, 16, 0, 18, 0, + 0, 0, 70, 14, 16, 0, + 14, 0, 0, 0, 55, 0, + 0, 9, 194, 0, 16, 0, + 16, 0, 0, 0, 166, 10, + 16, 0, 7, 0, 0, 0, + 6, 8, 16, 0, 14, 0, + 0, 0, 166, 2, 16, 0, + 14, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 16, 0, 0, 0, 118, 15, + 16, 0, 14, 0, 0, 0, + 55, 0, 0, 9, 226, 0, + 16, 0, 16, 0, 0, 0, + 86, 5, 16, 0, 7, 0, + 0, 0, 6, 6, 16, 0, + 14, 0, 0, 0, 86, 14, + 16, 0, 16, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 14, 0, 0, 0, + 6, 0, 16, 0, 7, 0, + 0, 0, 70, 14, 16, 0, + 14, 0, 0, 0, 70, 14, + 16, 0, 16, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 50, 0, 16, 0, + 14, 0, 0, 0, 70, 0, + 16, 0, 14, 0, 0, 0, + 70, 0, 16, 0, 14, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 14, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 9, 0, 0, 0, + 42, 0, 16, 0, 14, 0, + 0, 0, 42, 0, 16, 0, + 14, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 86, 0, 0, 5, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 86, 0, 0, 5, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 14, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 42, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 28, 0, 0, 5, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 7, + 66, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 13, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 22, 0, + 0, 1, 54, 0, 0, 5, + 18, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 13, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 10, 0, 16, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 18, 0, 16, 0, + 7, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 244, 255, + 255, 255, 85, 0, 0, 7, + 34, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 254, 255, + 255, 255, 254, 255, 255, 255, + 254, 255, 255, 255, 254, 255, + 255, 255, 30, 0, 0, 7, + 242, 0, 16, 0, 4, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 1, 0, 0, 10, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 254, 255, 255, 255, 254, 255, + 255, 255, 254, 255, 255, 255, + 254, 255, 255, 255, 30, 0, + 0, 7, 242, 0, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 30, 0, 0, 8, + 242, 0, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 8, 0, 0, 0, 6, 4, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 35, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 8, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 98, 0, 16, 0, + 2, 0, 0, 0, 6, 1, + 16, 0, 3, 0, 0, 0, + 6, 1, 16, 0, 8, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 35, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 34, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 33, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 43, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 253, 255, 125, 66, + 28, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 5, 0, 0, 0, + 79, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 40, 0, 0, 5, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 9, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 8, 0, 0, 0, 33, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 43, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 50, 0, 16, 0, + 12, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 1, 80, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 3, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 30, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 167, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 70, 254, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 8, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 128, 65, 0, + 0, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 98, 0, + 16, 0, 2, 0, 0, 0, + 6, 1, 16, 0, 3, 0, + 0, 0, 6, 1, 16, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 42, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 35, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 33, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 34, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 43, 0, 0, 5, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 253, 255, + 125, 66, 14, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 28, 0, 0, 5, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 10, + 34, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 10, 144, + 144, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 15, 0, 0, 0, + 55, 0, 0, 9, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 9, 66, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 64, 0, + 0, 0, 26, 144, 144, 128, + 65, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 38, 0, 0, 9, 0, 208, + 0, 0, 242, 0, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 86, 149, 144, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 35, 0, 0, 9, 242, 0, + 16, 0, 8, 0, 0, 0, + 166, 10, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 9, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 32, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, + 32, 0, 0, 0, 85, 0, + 0, 7, 242, 0, 16, 0, + 8, 0, 0, 0, 134, 13, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 79, 0, 0, 7, + 242, 0, 16, 0, 10, 0, + 0, 0, 134, 13, 16, 0, + 8, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 82, 0, + 16, 0, 11, 0, 0, 0, + 6, 1, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 5, + 162, 0, 16, 0, 11, 0, + 0, 0, 6, 8, 16, 0, + 8, 0, 0, 0, 55, 0, + 0, 9, 242, 0, 16, 0, + 11, 0, 0, 0, 6, 5, + 16, 0, 10, 0, 0, 0, + 70, 14, 16, 0, 11, 0, + 0, 0, 22, 11, 16, 0, + 11, 0, 0, 0, 54, 0, + 0, 5, 82, 0, 16, 0, + 8, 0, 0, 0, 166, 11, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 230, 14, 16, 0, 10, 0, + 0, 0, 214, 8, 16, 0, + 8, 0, 0, 0, 134, 13, + 16, 0, 8, 0, 0, 0, + 40, 0, 0, 5, 50, 0, + 16, 0, 8, 0, 0, 0, + 214, 5, 16, 0, 11, 0, + 0, 0, 40, 0, 0, 5, + 194, 0, 16, 0, 8, 0, + 0, 0, 6, 4, 16, 0, + 5, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 5, 0, 0, 0, 134, 0, + 16, 0, 11, 0, 0, 0, + 30, 0, 0, 7, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 98, 0, 16, 0, 2, 0, + 0, 0, 6, 1, 16, 0, + 5, 0, 0, 0, 6, 1, + 16, 0, 5, 0, 0, 0, + 30, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 35, 0, + 0, 9, 34, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 86, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 86, 0, 0, 5, 66, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 28, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 7, 18, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 12, 0, 0, 0, 30, 0, + 0, 7, 34, 0, 16, 0, + 12, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 22, 0, 0, 1, + 54, 0, 0, 5, 34, 0, + 16, 0, 12, 0, 0, 0, + 1, 64, 0, 0, 6, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 0, + 7, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 8, + 50, 0, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 168, 0, 0, 8, + 50, 240, 17, 0, 0, 0, + 0, 0, 10, 64, 2, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 70, 0, 16, 0, + 12, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 198, 0, + 16, 0, 6, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 8, 0, 0, 0, + 167, 0, 0, 9, 98, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 241, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 12, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 134, 0, + 16, 0, 3, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 167, 0, 0, 9, 98, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 241, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 134, 0, + 16, 0, 4, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 31, 0, + 4, 3, 58, 0, 16, 0, + 1, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 167, 0, 0, 9, 98, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 241, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 134, 0, + 16, 0, 3, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 31, 0, + 4, 3, 10, 0, 16, 0, + 2, 0, 0, 0, 167, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 240, + 17, 0, 0, 0, 0, 0, + 30, 0, 0, 6, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 167, 0, 0, 9, 98, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 6, 241, + 17, 0, 0, 0, 0, 0, + 167, 0, 0, 9, 50, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 28, 0, 0, 0, 70, 240, + 17, 0, 0, 0, 0, 0, + 79, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 167, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 16, 0, + 0, 0, 6, 240, 17, 0, + 0, 0, 0, 0, 168, 0, + 0, 8, 50, 240, 17, 0, + 0, 0, 0, 0, 10, 64, + 2, 0, 1, 64, 0, 0, + 16, 0, 0, 0, 134, 0, + 16, 0, 2, 0, 0, 0, + 168, 0, 0, 8, 50, 240, + 17, 0, 0, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 167, 0, 0, 8, 146, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 28, 0, 0, 0, + 6, 244, 17, 0, 0, 0, + 0, 0, 41, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 31, 0, 0, 0, + 167, 0, 0, 8, 50, 0, + 16, 0, 1, 0, 0, 0, + 10, 64, 2, 0, 1, 64, + 0, 0, 16, 0, 0, 0, + 70, 240, 17, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 168, 0, 0, 9, + 242, 224, 17, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 62, 0, 0, 1 +}; diff --git a/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode456CS.pdb b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode456CS.pdb new file mode 100644 index 0000000000000000000000000000000000000000..266c5a618dba55c3cec266a11c81422a51833253 Binary files /dev/null and b/Kits/DirectXTex/Shaders/Compiled/BC7Encode_TryMode456CS.pdb differ diff --git a/Kits/DirectXTex/filters.h b/Kits/DirectXTex/filters.h new file mode 100644 index 0000000000000000000000000000000000000000..582c48c0787eaab32b7d9a4a8088c67703356bb2 --- /dev/null +++ b/Kits/DirectXTex/filters.h @@ -0,0 +1,423 @@ +//------------------------------------------------------------------------------------- +// filters.h +// +// Utility header with helpers for implementing image filters +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include + +#include + +#include "scoped.h" + +namespace DirectX +{ + +//------------------------------------------------------------------------------------- +// Box filtering helpers +//------------------------------------------------------------------------------------- + +XMGLOBALCONST XMVECTORF32 g_boxScale = { { { 0.25f, 0.25f, 0.25f, 0.25f } } }; +XMGLOBALCONST XMVECTORF32 g_boxScale3D = { { { 0.125f, 0.125f, 0.125f, 0.125f } } }; + +#define AVERAGE4( res, p0, p1, p2, p3 ) \ +{ \ + XMVECTOR v = XMVectorAdd( (p0), (p1) ); \ + v = XMVectorAdd( v, (p2) ); \ + v = XMVectorAdd( v, (p3) ); \ + res = XMVectorMultiply( v, g_boxScale ); \ +} + +#define AVERAGE8( res, p0, p1, p2, p3, p4, p5, p6, p7) \ +{ \ + XMVECTOR v = XMVectorAdd( (p0), (p1) ); \ + v = XMVectorAdd( v, (p2) ); \ + v = XMVectorAdd( v, (p3) ); \ + v = XMVectorAdd( v, (p4) ); \ + v = XMVectorAdd( v, (p5) ); \ + v = XMVectorAdd( v, (p6) ); \ + v = XMVectorAdd( v, (p7) ); \ + res = XMVectorMultiply( v, g_boxScale3D ); \ +} + + +//------------------------------------------------------------------------------------- +// Linear filtering helpers +//------------------------------------------------------------------------------------- + +struct LinearFilter +{ + size_t u0; + float weight0; + size_t u1; + float weight1; +}; + +inline void _CreateLinearFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf) +{ + assert(source > 0); + assert(dest > 0); + assert(lf != 0); + + float scale = float(source) / float(dest); + + // Mirror is the same case as clamp for linear + + for (size_t u = 0; u < dest; ++u) + { + float srcB = (float(u) + 0.5f) * scale + 0.5f; + + ptrdiff_t isrcB = ptrdiff_t(srcB); + ptrdiff_t isrcA = isrcB - 1; + + if (isrcA < 0) + { + isrcA = (wrap) ? (source - 1) : 0; + } + + if (size_t(isrcB) >= source) + { + isrcB = (wrap) ? 0 : (source - 1); + } + + float weight = 1.0f + float(isrcB) - srcB; + + auto& entry = lf[u]; + entry.u0 = size_t(isrcA); + entry.weight0 = weight; + + entry.u1 = size_t(isrcB); + entry.weight1 = 1.0f - weight; + } +} + +#define BILINEAR_INTERPOLATE( res, x, y, r0, r1 ) \ + res = ( y.weight0 * ( (r0)[ x.u0 ] * x.weight0 + (r0)[ x.u1 ] * x.weight1 ) ) \ + + ( y.weight1 * ( (r1)[ x.u0 ] * x.weight0 + (r1)[ x.u1 ] * x.weight1 ) ) + +#define TRILINEAR_INTERPOLATE( res, x, y, z, r0, r1, r2, r3 ) \ + res = ( z.weight0 * ( ( y.weight0 * ( (r0)[ x.u0 ] * x.weight0 + (r0)[ x.u1 ] * x.weight1 ) ) \ + + ( y.weight1 * ( (r1)[ x.u0 ] * x.weight0 + (r1)[ x.u1 ] * x.weight1 ) ) ) ) \ + + ( z.weight1 * ( ( y.weight0 * ( (r2)[ x.u0 ] * x.weight0 + (r2)[ x.u1 ] * x.weight1 ) ) \ + + ( y.weight1 * ( (r3)[ x.u0 ] * x.weight0 + (r3)[ x.u1 ] * x.weight1 ) ) ) ) + + +//------------------------------------------------------------------------------------- +// Cubic filtering helpers +//------------------------------------------------------------------------------------- + +XMGLOBALCONST XMVECTORF32 g_cubicThird = { { { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } } }; +XMGLOBALCONST XMVECTORF32 g_cubicSixth = { { { 1.f / 6.f, 1.f / 6.f, 1.f / 6.f, 1.f / 6.f } } }; +XMGLOBALCONST XMVECTORF32 g_cubicHalf = { { { 1.f / 2.f, 1.f / 2.f, 1.f / 2.f, 1.f / 2.f } } }; + +inline ptrdiff_t bounduvw(ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror) +{ + if (wrap) + { + if (u < 0) + { + u = maxu + u + 1; + } + else if (u > maxu) + { + u = u - maxu - 1; + } + } + else if (mirror) + { + if (u < 0) + { + u = (-u) - 1; + } + else if (u > maxu) + { + u = maxu - (u - maxu - 1); + } + } + + // Handles clamp, but also a safety factor for degenerate images for wrap/mirror + u = std::min(u, maxu); + u = std::max(u, 0); + + return u; +} + +struct CubicFilter +{ + size_t u0; + size_t u1; + size_t u2; + size_t u3; + float x; +}; + +inline void _CreateCubicFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf) +{ + assert(source > 0); + assert(dest > 0); + assert(cf != 0); + + float scale = float(source) / float(dest); + + for (size_t u = 0; u < dest; ++u) + { + float srcB = (float(u) + 0.5f) * scale - 0.5f; + + ptrdiff_t isrcB = bounduvw(ptrdiff_t(srcB), source - 1, wrap, mirror); + ptrdiff_t isrcA = bounduvw(isrcB - 1, source - 1, wrap, mirror); + ptrdiff_t isrcC = bounduvw(isrcB + 1, source - 1, wrap, mirror); + ptrdiff_t isrcD = bounduvw(isrcB + 2, source - 1, wrap, mirror); + + auto& entry = cf[u]; + entry.u0 = size_t(isrcA); + entry.u1 = size_t(isrcB); + entry.u2 = size_t(isrcC); + entry.u3 = size_t(isrcD); + + float x = srcB - float(isrcB); + entry.x = x; + } +} + +#define CUBIC_INTERPOLATE( res, dx, p0, p1, p2, p3 ) \ +{ \ + XMVECTOR a0 = (p1); \ + XMVECTOR d0 = (p0) - a0; \ + XMVECTOR d2 = (p2) - a0; \ + XMVECTOR d3 = (p3) - a0; \ + XMVECTOR a1 = d2 - g_cubicThird*d0 - g_cubicSixth*d3; \ + XMVECTOR a2 = g_cubicHalf*d0 + g_cubicHalf*d2; \ + XMVECTOR a3 = g_cubicSixth*d3 - g_cubicSixth*d0 - g_cubicHalf*d2; \ + XMVECTOR vdx = XMVectorReplicate( dx ); \ + XMVECTOR vdx2 = vdx * vdx; \ + XMVECTOR vdx3 = vdx2 * vdx; \ + res = a0 + a1*vdx + a2*vdx2 + a3*vdx3; \ +} + + +//------------------------------------------------------------------------------------- +// Triangle filtering helpers +//------------------------------------------------------------------------------------- + +namespace TriangleFilter +{ + struct FilterTo + { + size_t u; + float weight; + }; + + struct FilterFrom + { + size_t count; + size_t sizeInBytes; + FilterTo to[1]; // variable-sized array + }; + + struct Filter + { + size_t sizeInBytes; + size_t totalSize; + FilterFrom from[1]; // variable-sized array + }; + + struct TriangleRow + { + size_t remaining; + TriangleRow* next; + ScopedAlignedArrayXMVECTOR scanline; + + TriangleRow() : remaining(0), next(nullptr) {} + }; + + static const size_t TF_FILTER_SIZE = sizeof(Filter) - sizeof(FilterFrom); + static const size_t TF_FROM_SIZE = sizeof(FilterFrom) - sizeof(FilterTo); + static const size_t TF_TO_SIZE = sizeof(FilterTo); + + static const float TF_EPSILON = 0.00001f; + + inline HRESULT _Create(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr& tf) + { + assert(source > 0); + assert(dest > 0); + + float scale = float(dest) / float(source); + float scaleInv = 0.5f / scale; + + // Determine storage required for filter and allocate memory if needed + size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE; + float repeat = (wrap) ? 1.f : 0.f; + + for (size_t u = 0; u < source; ++u) + { + float src = float(u) - 0.5f; + float destMin = src * scale; + float destMax = destMin + scale; + + totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t(destMax - destMin + repeat + 1.f) * TF_TO_SIZE * 2; + } + + uint8_t* pFilter = nullptr; + + if (tf) + { + // See if existing filter memory block is large enough to reuse + if (tf->totalSize >= totalSize) + { + pFilter = reinterpret_cast(tf.get()); + } + else + { + // Need to reallocate filter memory block + tf.reset(nullptr); + } + } + + if (!tf) + { + // Allocate filter memory block + pFilter = new (std::nothrow) uint8_t[totalSize]; + if (!pFilter) + return E_OUTOFMEMORY; + + tf.reset(reinterpret_cast(pFilter)); + tf->totalSize = totalSize; + } + + assert(pFilter != 0); + _Analysis_assume_(pFilter != 0); + + // Filter setup + size_t sizeInBytes = TF_FILTER_SIZE; + size_t accumU = 0; + float accumWeight = 0.f; + + for (size_t u = 0; u < source; ++u) + { + // Setup from entry + size_t sizeFrom = sizeInBytes; + auto pFrom = reinterpret_cast(pFilter + sizeInBytes); + sizeInBytes += TF_FROM_SIZE; + + if (sizeInBytes > totalSize) + return E_FAIL; + + size_t toCount = 0; + + // Perform two passes to capture the influences from both sides + for (size_t j = 0; j < 2; ++j) + { + float src = float(u + j) - 0.5f; + + float destMin = src * scale; + float destMax = destMin + scale; + + if (!wrap) + { + // Clamp + if (destMin < 0.f) + destMin = 0.f; + if (destMax > float(dest)) + destMax = float(dest); + } + + for (auto k = static_cast(floorf(destMin)); float(k) < destMax; ++k) + { + float d0 = float(k); + float d1 = d0 + 1.f; + + size_t u0; + if (k < 0) + { + // Handle wrap + u0 = size_t(k + ptrdiff_t(dest)); + } + else if (k >= ptrdiff_t(dest)) + { + // Handle wrap + u0 = size_t(k - ptrdiff_t(dest)); + } + else + { + u0 = size_t(k); + } + + // Save previous accumulated weight (if any) + if (u0 != accumU) + { + if (accumWeight > TF_EPSILON) + { + auto pTo = reinterpret_cast(pFilter + sizeInBytes); + sizeInBytes += TF_TO_SIZE; + ++toCount; + + if (sizeInBytes > totalSize) + return E_FAIL; + + pTo->u = accumU; + pTo->weight = accumWeight; + } + + accumWeight = 0.f; + accumU = u0; + } + + // Clip destination + if (d0 < destMin) + d0 = destMin; + if (d1 > destMax) + d1 = destMax; + + // Calculate average weight over destination pixel + + float weight; + if (!wrap && src < 0.f) + weight = 1.f; + else if (!wrap && ((src + 1.f) >= float(source))) + weight = 0.f; + else + weight = (d0 + d1) * scaleInv - src; + + accumWeight += (d1 - d0) * (j ? (1.f - weight) : weight); + } + } + + // Store accumulated weight + if (accumWeight > TF_EPSILON) + { + auto pTo = reinterpret_cast(pFilter + sizeInBytes); + sizeInBytes += TF_TO_SIZE; + ++toCount; + + if (sizeInBytes > totalSize) + return E_FAIL; + + pTo->u = accumU; + pTo->weight = accumWeight; + } + + accumWeight = 0.f; + + // Finalize from entry + pFrom->count = toCount; + pFrom->sizeInBytes = sizeInBytes - sizeFrom; + } + + tf->sizeInBytes = sizeInBytes; + + return S_OK; + } + +}; // namespace TriangleFilter + +}; // namespace DirectX \ No newline at end of file diff --git a/Kits/DirectXTex/scoped.h b/Kits/DirectXTex/scoped.h new file mode 100644 index 0000000000000000000000000000000000000000..6e553c7f24a72367ccb1e757564a868af8bdba29 --- /dev/null +++ b/Kits/DirectXTex/scoped.h @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------------- +// scoped.h +// +// Utility header with helper classes for exception-safe handling of resources +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +//--------------------------------------------------------------------------------- +struct aligned_deleter { void operator()(void* p) { _aligned_free(p); } }; + +typedef std::unique_ptr ScopedAlignedArrayFloat; + +typedef std::unique_ptr ScopedAlignedArrayXMVECTOR; + +//--------------------------------------------------------------------------------- +struct handle_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) CloseHandle(h); } }; + +typedef std::unique_ptr ScopedHandle; + +inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } + +//--------------------------------------------------------------------------------- +struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } }; + +typedef std::unique_ptr ScopedFindHandle; + +//--------------------------------------------------------------------------------- +class auto_delete_file +{ +public: + auto_delete_file(HANDLE hFile) : m_handle(hFile) {} + + auto_delete_file(const auto_delete_file&) = delete; + auto_delete_file& operator=(const auto_delete_file&) = delete; + + ~auto_delete_file() + { + if (m_handle) + { + FILE_DISPOSITION_INFO info = { 0 }; + info.DeleteFile = TRUE; + (void)SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, sizeof(info)); + } + } + + void clear() { m_handle = 0; } + +private: + HANDLE m_handle; +}; diff --git a/Media/Sounds/MusicMono_xma.wav b/Media/Sounds/MusicMono_xma.wav new file mode 100644 index 0000000000000000000000000000000000000000..6f5f41883fb80eae446450df6c4cb71608aa90a4 Binary files /dev/null and b/Media/Sounds/MusicMono_xma.wav differ diff --git a/Media/Sounds/xmadroid.xwb b/Media/Sounds/xmadroid.xwb new file mode 100644 index 0000000000000000000000000000000000000000..acc29f0539042533fc53cd6708f7d1f1cd462000 Binary files /dev/null and b/Media/Sounds/xmadroid.xwb differ diff --git a/Media/Textures/1920x1080.DDS b/Media/Textures/1920x1080.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c151a6d3cf34ba4048e2481db918144386fcfe6d Binary files /dev/null and b/Media/Textures/1920x1080.DDS differ diff --git a/Media/Textures/3840x2160.DDS b/Media/Textures/3840x2160.DDS new file mode 100644 index 0000000000000000000000000000000000000000..463668a040b932edc1d4a806b3b284935c472b1a Binary files /dev/null and b/Media/Textures/3840x2160.DDS differ diff --git a/Media/Textures/FrontPanelPresent.png b/Media/Textures/FrontPanelPresent.png new file mode 100644 index 0000000000000000000000000000000000000000..bdc19ce6f5bbc2e5bd32429811ab82ad2c2518d2 Binary files /dev/null and b/Media/Textures/FrontPanelPresent.png differ diff --git a/Media/Textures/NoFrontPanel.png b/Media/Textures/NoFrontPanel.png new file mode 100644 index 0000000000000000000000000000000000000000..d35b400105b4cee135c27bf14469fb096bb89a27 Binary files /dev/null and b/Media/Textures/NoFrontPanel.png differ diff --git a/README.md b/README.md index 301525bdd7c1f5ca806402ffff2b9a54a732a902..486967305de0fbc5d7ea9cfdb1e4b1a4e6281104 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,12 @@ This repo contains game development samples written by the Microsoft Xbox Advanc * ``Tools`` * ``PCSamples`` contains samples for the classic Win32 desktop PC platform * ``IntroGraphics`` +* ``XDKSamples`` contains samples the Xbox One platform using the Xbox One XDK + * ``Audio`` + * ``IntroGraphics`` + * ``Graphics`` + * ``System`` + * ``Tools`` ## Samples by category @@ -20,14 +26,17 @@ This repo contains game development samples written by the Microsoft Xbox Advanc - - - + + + + + - - + + + @@ -43,6 +52,8 @@ This repo contains game development samples written by the Microsoft Xbox Advanc + + @@ -50,6 +61,8 @@ This repo contains game development samples written by the Microsoft Xbox Advanc + + @@ -57,21 +70,29 @@ This repo contains game development samples written by the Microsoft Xbox Advanc + + + + + + + + @@ -79,11 +100,20 @@ This repo contains game development samples written by the Microsoft Xbox Advanc + + + + + + + + +
Spatial audioSimple playback3D playbackAdvanced audioSimple playback UWPSimple playback XDK3D playback UWPAdvanced audio UWPAdvanced audio XDK
XAudio2Basic audio playback3D playbackBasic audio UWPBasic audio XDK3D playback UWP
WASAPIBasic drawing UWP DX11 UWP DX12XDK DX11XDK DX12 PC DX11 PC DX12
Basic texturing UWP DX11 UWP DX12XDK DX11XDK DX12 PC DX11 PC DX12
Basic lighting UWP DX11 UWP DX12XDK DX11XDK DX12
Bezier UWP DX11 UWP DX12XDK DX11XDK DX12
DirectCompute UWP DX11 UWP DX12XDK DX11XDK DX12
DirectX Tool Kit UWP DX11 UWP DX12XDK DX11XDK DX12 PC DX11 PC DX12
Instancing UWP DX11 UWP DX12XDK DX11XDK DX12
Multisample Antialiasing UWP DX11 UWP DX12XDK DX11XDK DX12
Xbox One Device SetupXDK DX11XDK DX12
@@ -91,7 +121,14 @@ This repo contains game development samples written by the Microsoft Xbox Advanc - + + + + + + + +
Physically Based RenderingPhysically Based RenderingUWPXDK
High-Dynamic Range RenderingXDK DX11XDK DX12
@@ -99,35 +136,85 @@ This repo contains game development samples written by the Microsoft Xbox Advanc + - - + + + + + + + +
UWP CPU Sets Memory StatisticsSystem InformationDirectXMath
XDKAsync I/OData BreakpointsMemory Banks
+ + + + + + + + + + +
System InformationUWPXDK
DirectXMathUWPXDK
- - - - + + + + + + + + + + + + + + + + + - - - + + + +
GamepadC++/CXC++/WinRTVibrationRawUWPXDKUWP (C++/WinRT)XDK (C++/WinRT)
Gamepad VibrationUWPXDK
Raw Game ControllerUWP
FlightStickXDK
InputInterfacingMouseUser-pairingInterfacing UWPMouse UWPUser-pairing UWP
+ + - + + +
Process Lifetime ManagementPLMUWP PLMXDK PLM Extended Execution
+ + - + + + +
LocalizationNLSUWPXDK
+ + + + + + + + +
Xbox One X Front PanelBasicTextDemoDolphinGame
@@ -139,6 +226,22 @@ This repo contains game development samples written by the Microsoft Xbox Advanc + + + + + + + +
CrashDumpSymbol ProxyOS PrimitiveTexConv for Xbox
+ + + + + + +
FrontPanel FontFrontPanel Font Viewer
+ # Requirements ## UWP apps @@ -149,6 +252,11 @@ Use of the Visual Studio 2017 update v15.3 is recommended. > The *Windows 10 SDK (10.0.14393.0)* is required to support ``WindowsTargetPlatformMinVersion`` set the Windows 10 Anniversary Update in many of the samples that work on both versions of Windows 10. +## XDK apps +* Xbox One Development Kit +* Xbox One XDK (specific version requirements covered in each sample's readme) +* Visual Studio 2015 or Visual Studio 2017 (_via upgrade in place_) + ## PC apps * Visual Studio 2015 Update 3 -or- Visual Studio 2017 (_via upgrade in place_) with the *Desktop development with C++* workload and *Windows 8.1 SDK* component. * _DirectX 11:_ Windows 7 Service Pack 1 with the DirectX 11.1 Runtime via [KB2670838](http://support.microsoft.com/kb/2670838) or later. diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.cpp b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.cpp new file mode 100644 index 0000000000000000000000000000000000000000..578e68d0b1dbd5d15ca6cad54dc998f409d16312 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.cpp @@ -0,0 +1,1092 @@ +//-------------------------------------------------------------------------------------- +// AdvancedSpatialSoundsXDK.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "AdvancedSpatialSoundsXDK.h" +#include "WAVFileReader.h" + +#include "ATGColors.h" + +static const LPCWSTR g_FileList[] = { + L"Jungle_RainThunder_mix714.wav", + L"ChannelIDs714.wav", + nullptr +}; + +static const int numFiles = 2; + +#define MAX_X 100 +#define MIN_X -100 +#define MAX_Y 100 +#define MIN_Y -100 +#define MAX_Z 100 +#define MIN_Z -100 +#define MAX_VEL 3 +#define MAX_RADIUS 90 +#define MIN_RADIUS 10 +#define CURVE_START 30 +#define CURVE_END 170 +#define DRAW_BACK_WALL .3f +#define DRAW_POINT_SCALE 40.f +#define DRAW_POINT_MIN_SCALE 2.f + +static const LPCWSTR g_bedFileList[] = { + L"assets\\Jungle_RainThunder_5.1_mixdown.wav", + L"assets\\Jungle_RainThunder_SideSurroundL-R.wav", + L"assets\\Jungle_RainThunder_TopFrontL-R.wav", + L"assets\\Jungle_RainThunder_TopRearL-R.wav", + nullptr +}; + +static const int g_numBedFiles = 4; + +static const LPCWSTR g_pointFileList[] = { + L"assets\\SFX_height_birdHawk01.wav", + L"assets\\SFX_height_birdLoon01.wav", + L"assets\\SFX_moving_BirdFlap01.wav", + L"assets\\SFX_moving_birdFlicker01.wav", + L"assets\\SFX_moving_birdFlycatcher01.wav", + L"assets\\SFX_moving_birdLark01.wav", + L"assets\\SFX_moving_birdLoop01.wav", + L"assets\\SFX_moving_birdLoop02.wav", + L"assets\\SFX_moving_birdLoop03.wav", + L"assets\\SFX_moving_birdLoop04.wav", + L"assets\\SFX_moving_birdLoop05.wav", + L"assets\\SFX_moving_birdLoop06.wav", + L"assets\\SFX_moving_birdSparrow01.wav", + L"assets\\SFX_moving_birdSparrow02.wav", + L"assets\\SFX_moving_birdWarbler01.wav", + L"assets\\SFX_moving_Fly01.wav", + L"assets\\SFX_moving_Fly02.wav", + L"assets\\SFX_stationary_cicada01.wav", + L"assets\\SFX_stationary_grasshopper01.wav", + L"assets\\SFX_stationary_grasshopper02.wav", + nullptr +}; + +static const LPCWSTR g_pointFileNames[] = { + L"Hawk", + L"Loon", + L"BirdFlap", + L"Flicker", + L"Flycatcher", + L"Lark", + L"Loop 1", + L"Loop 2", + L"Loop 3", + L"Loop 4", + L"Loop 5", + L"Loop 6", + L"Sparrow 1", + L"Sparrow 2", + L"Warbler", + L"Fly 1", + L"Fly 2", + L"Cicada", + L"Grasshopper 1", + L"Grasshopper 2", + nullptr +}; +static const int g_numPointFiles = 20; + +static const LPCWSTR g_travelTypeNames[] = { + L"Linear", + L"Bounce", + L"Round", + nullptr +}; + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +VOID CALLBACK SpatialWorkCallback(_Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context, _Inout_ PTP_WORK Work) +{ + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + Sample * Sink = (Sample *)Context; + Work; + Instance; + + while (Sink->m_bThreadActive) + { + while (Sink->m_bPlayingSound && Sink->m_Renderer->IsActive()) + { + // Wait for a signal from the audio-engine to start the next processing pass + if (WaitForSingleObject(Sink->m_Renderer->m_bufferCompletionEvent, 100) != WAIT_OBJECT_0) + { + //make a call to stream to see why we didn't get a signal after 100ms + hr = Sink->m_Renderer->m_SpatialAudioStream->Reset(); + + //if we have an error, tell the renderer to reset + if (hr != S_OK) + { + Sink->m_Renderer->Reset(); + } + continue; + } + + UINT32 frameCount; + UINT32 availableObjectCount; + + // Begin the process of sending object data and metadata + // Get the number of active object that can be used to send object-data + // Get the number of frame count that each buffer be filled with  + hr = Sink->m_Renderer->m_SpatialAudioStream->BeginUpdatingAudioObjects( + &availableObjectCount, + &frameCount); + //if we have an error, tell the renderer to reset + if (hr != S_OK) + { + Sink->m_Renderer->Reset(); + continue; + } + + Sink->m_availableObjects = availableObjectCount; + + for (int chan = 0; chan < MAX_CHANNELS; chan++) + { + //Activate the object if not yet done + if (Sink->m_bedChannels[chan].object == nullptr) + { + // If this method called more than activeObjectCount times + // It will fail with this error HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) + hr = Sink->m_Renderer->m_SpatialAudioStream->ActivateSpatialAudioObject( + Sink->m_bedChannels[chan].objType, + &Sink->m_bedChannels[chan].object); + if (FAILED(hr)) + { + continue; + } + + } + + //Get the object buffer + BYTE* buffer = nullptr; + UINT32 bytecount; + hr = Sink->m_bedChannels[chan].object->GetBuffer(&buffer, &bytecount); + if (FAILED(hr)) + { + continue; + } + + Sink->m_bedChannels[chan].object->SetVolume(Sink->m_bedChannels[chan].volume); + + UINT32 readsize = bytecount; + + for (UINT32 i = 0; i < readsize; i++) + { + UINT32 fileLoc = Sink->m_bedChannels[chan].curBufferLoc; + if (chan < Sink->m_numChannels) + { + buffer[i] = Sink->m_bedChannels[chan].wavBuffer[fileLoc]; + } + else + { + buffer[i] = 0; + } + + Sink->m_bedChannels[chan].curBufferLoc++; + if (Sink->m_bedChannels[chan].curBufferLoc == Sink->m_bedChannels[chan].bufferSize) + { + Sink->m_bedChannels[chan].curBufferLoc = 0; + } + + + } + + } + //Update the point sounds + bool deleteSound = false; + + std::lock_guard lock(Sink->MutexLock); + for (std::vector::iterator it = Sink->m_pointSounds.begin(); it != Sink->m_pointSounds.end(); it++) + { + //Activate the object if not yet done + if (it->object == nullptr) + { + // If this method called more than activeObjectCount times + // It will fail with this error HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) + hr = Sink->m_Renderer->m_SpatialAudioStream->ActivateSpatialAudioObject( + AudioObjectType_Dynamic, + &it->object); + if (FAILED(hr)) + { + continue; + } + } + + //Get the object buffer + BYTE* buffer = nullptr; + UINT32 bytecount; + hr = it->object->GetBuffer(&buffer, &bytecount); + if (FAILED(hr)) + { + continue; + } + + if (!it->isPlaying) + { + // Set end of stream for the last buffer  + hr = it->object->SetEndOfStream(0); + + // Last block of data in the object, release the audio object, + // so the resources can be recycled and used for another object + it->object = nullptr; + it->curBufferLoc = 0; + + deleteSound = true; + } + else + { + it->object->SetPosition(it->posX, it->posY, it->posZ); + it->object->SetVolume(it->volume); + + for (UINT32 i = 0; i < frameCount * 4; i++) + { + UINT32 fileLoc = it->curBufferLoc; + buffer[i] = it->wavBuffer[fileLoc]; + it->curBufferLoc++; + if (it->curBufferLoc == it->bufferSize) + { + it->curBufferLoc = 0; + } + } + } + } + + if (deleteSound) + { + Sink->m_pointSounds.pop_back(); + } + + // Let the audio-engine know that the object data are available for processing now + hr = Sink->m_Renderer->m_SpatialAudioStream->EndUpdatingAudioObjects(); + if (FAILED(hr)) + { + //Due to known issue is current release, an erroneous error will be produced + // after removing dynamic objects. Until fixed, just ignore error here + // and the sample will continue to function as expected. + //Sink->m_Renderer->Reset(); + } + } + } +} + + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(); + m_fileLoaded = false; + m_Renderer = nullptr; + m_bThreadActive = false; + m_bPlayingSound = false; + m_curFile = 0; + m_usedObjects = 0; + m_availableObjects = 0; +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + InitializeSpatialStream(); + + srand((unsigned int)time(NULL)); + + m_boundingBox = BoundingBox(XMFLOAT3(), XMFLOAT3((MAX_X - MIN_X) / 2, (MAX_Y - MIN_Y) / 2, (MAX_Z - MIN_Z) / 2)); + + for (UINT32 i = 0; i < MAX_CHANNELS; i++) + { + m_bedChannels[i].bufferSize = 0; + m_bedChannels[i].curBufferLoc = 0; + m_bedChannels[i].volume = 1.f; + m_bedChannels[i].object = nullptr; + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + + +//-------------------------------------------------------------------------------------- +// Name: DrawRoom() +// Desc: Draws the room +//-------------------------------------------------------------------------------------- +void XM_CALLCONV Sample::DrawRoom(FXMVECTOR color) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw room"); + + context->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF); + context->OMSetDepthStencilState(m_states->DepthNone(), 0); + context->RSSetState(m_states->CullNone()); + + m_batchEffect->Apply(context); + + context->IASetInputLayout(m_batchInputLayout.Get()); + + m_batch->Begin(); + + XMVECTORF32 points[4]; + points[0] = { -DRAW_BACK_WALL, -DRAW_BACK_WALL, 0.f }; + points[1] = { -DRAW_BACK_WALL, DRAW_BACK_WALL, 0.f }; + points[2] = { DRAW_BACK_WALL, DRAW_BACK_WALL, 0.f }; + points[3] = { DRAW_BACK_WALL, -DRAW_BACK_WALL, 0.f }; + + XMVECTORF32 edgePoints[4]; + edgePoints[0] = { -1.f, -1.f, 0.f }; + edgePoints[1] = { -1.f, 1.f, 0.f }; + edgePoints[2] = { 1.f, 1.f, 0.f }; + edgePoints[3] = { 1.f, -1.f, 0.f }; + + VertexPositionColor v[4]; + v[0] = VertexPositionColor(points[0], color); + v[1] = VertexPositionColor(points[1], color); + v[2] = VertexPositionColor(points[2], color); + v[3] = VertexPositionColor(points[3], color); + m_batch->DrawLine(v[0], v[1]); + m_batch->DrawLine(v[1], v[2]); + m_batch->DrawLine(v[2], v[3]); + m_batch->DrawLine(v[3], v[0]); + + VertexPositionColor edge[4]; + edge[0] = VertexPositionColor(edgePoints[0], color); + edge[1] = VertexPositionColor(edgePoints[1], color); + edge[2] = VertexPositionColor(edgePoints[2], color); + edge[3] = VertexPositionColor(edgePoints[3], color); + + for (size_t i = 0; i <= 4; ++i) + { + m_batch->DrawLine(v[i], edge[i]); + } + + m_batch->End(); + + PIXEndEvent(context); +} + + +//-------------------------------------------------------------------------------------- +// Name: DrawSound() +// Desc: Draws a sound point +//-------------------------------------------------------------------------------------- +void XM_CALLCONV Sample::DrawSound(float x, float y, float z, FXMVECTOR color) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw point"); + + context->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF); + context->OMSetDepthStencilState(m_states->DepthNone(), 0); + context->RSSetState(m_states->CullNone()); + + m_batchEffect->Apply(context); + + context->IASetInputLayout(m_batchInputLayout.Get()); + + m_batch->Begin(); + + //Z MIN = 0, MAX = 1 + x = (x - MIN_X) / (MAX_X - MIN_X); + y = (y - MIN_Y) / (MAX_Y - MIN_Y); + z = (z - MIN_Z) / (MAX_Z - MIN_Z); + float scale = z * DRAW_POINT_SCALE + DRAW_POINT_MIN_SCALE; + + RECT drawspace = m_deviceResources->GetOutputSize(); + + float backWallWidth = DRAW_BACK_WALL * drawspace.right; + float backWallHeight = DRAW_BACK_WALL * drawspace.bottom; + + float lowBoundX = (drawspace.right - backWallWidth) * (1 - z) / 2; + float lowBoundY = (drawspace.bottom - backWallHeight) * (1 - z) / 2; + float highBoundX = drawspace.right - lowBoundX; + float highBoundY = drawspace.bottom - lowBoundY; + + x = x * (highBoundX - lowBoundX) + lowBoundX; + y = y * (highBoundY - lowBoundY) + lowBoundY; + + drawspace.bottom = (LONG)(y + scale); + drawspace.top = (LONG)y; + drawspace.left = (LONG)x; + drawspace.right = (LONG)(x + scale); + + m_spriteBatch->Draw(m_circle.Get(), drawspace, color); + + m_batch->End(); + + PIXEndEvent(context); +} + + +//-------------------------------------------------------------------------------------- +// Name: DrawListener() +// Desc: Draws a sound point +//-------------------------------------------------------------------------------------- +void XM_CALLCONV Sample::DrawListener(FXMVECTOR color) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw listener"); + + context->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF); + context->OMSetDepthStencilState(m_states->DepthNone(), 0); + context->RSSetState(m_states->CullNone()); + + m_batchEffect->Apply(context); + + context->IASetInputLayout(m_batchInputLayout.Get()); + + m_batch->Begin(); + + float scale = .035f; + + XMVECTORF32 points[3]; + points[0] = { -scale, -scale, 0 }; + points[1] = { scale, -scale, 0 }; + points[2] = { 0, .014f, 0 }; + + VertexPositionColor v[3]; + v[0] = VertexPositionColor(points[0], color); + v[1] = VertexPositionColor(points[1], color); + v[2] = VertexPositionColor(points[2], color); + m_batch->DrawTriangle(v[0], v[1], v[2]); + + m_batch->End(); + + PIXEndEvent(context); +} + + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + elapsedTime; + + //Are we resetting the renderer? This will happen if we get an invalid stream + // which can happen when render mode changes or device changes + if (m_Renderer->IsResetting()) + { + //clear out renderer + m_Renderer == NULL; + + // Create a new ISAC instance + m_Renderer = Microsoft::WRL::Make(); + + // Initialize Default Audio Device + m_Renderer->InitializeAudioDeviceAsync(); + + //Reset all the Objects that were being used + for (int chan = 0; chan < MAX_CHANNELS; chan++) + { + m_bedChannels[chan].object = nullptr; + } + for (std::vector::iterator it = m_pointSounds.begin(); it != m_pointSounds.end(); it++) + { + it->object = nullptr; + } + } + else if (m_Renderer->IsActive() && m_pointSounds.size() > m_Renderer->GetMaxDynamicObjects()) + { + //If we reactivated or available object changed and had more active objects than we do now, clear out those we cannot render + while (m_pointSounds.size() > m_Renderer->GetMaxDynamicObjects()) + { + m_pointSounds.pop_back(); + m_usedObjects--; + } + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_gamePadButtons.a == m_gamePadButtons.RELEASED) + { + //Start spatial worker thread + if (!m_bThreadActive) + { + //(re)load file to start again + m_fileLoaded = LoadBed(); + + //startup spatial thread + m_bThreadActive = true; + m_bPlayingSound = true; + m_workThread = CreateThreadpoolWork(SpatialWorkCallback, this, nullptr); + SubmitThreadpoolWork(m_workThread); + } + else + { + //stop and shutdown spatial worker thread + m_bThreadActive = false; + m_bPlayingSound = false; + WaitForThreadpoolWorkCallbacks(m_workThread, FALSE); + CloseThreadpoolWork(m_workThread); + } + + } + if (m_gamePadButtons.dpadUp == m_gamePadButtons.RELEASED) + { + if (m_usedObjects < m_availableObjects && m_bThreadActive && m_bPlayingSound) + { + PointSound tempChannel; + int randIndex = rand() % g_numPointFiles; + if (LoadPointFile(g_pointFileList[randIndex], &tempChannel)) + { + tempChannel.soundIndex = randIndex; + tempChannel.travelData.travelType = TravelType(rand() % 3); + tempChannel.travelData.boundingBox = m_boundingBox; + tempChannel.travelData.vel = static_cast (rand()) / static_cast (RAND_MAX / MAX_VEL); + tempChannel.posX = static_cast (rand()) / static_cast (RAND_MAX / MAX_X - MIN_X); + tempChannel.posY = static_cast (rand()) / static_cast (RAND_MAX / MAX_Y - MIN_Y); + tempChannel.posZ = static_cast (rand()) / static_cast (RAND_MAX / MAX_Z - MIN_Z); + + if (tempChannel.travelData.travelType == Round) + { + tempChannel.travelData.radius = static_cast (rand() % (MAX_RADIUS - MIN_RADIUS) + MIN_RADIUS); + } + else + { + float x = static_cast (rand()) / static_cast (RAND_MAX / MAX_X - MIN_X); + float y = static_cast (rand()) / static_cast (RAND_MAX / MAX_Y - MIN_Y); + float z = static_cast (rand()) / static_cast (RAND_MAX / MAX_Z - MIN_Z); + + XMVECTOR temp = { x, y, z }; + temp = XMVector3Normalize(temp); + XMStoreFloat3(&tempChannel.travelData.direction, temp); + } + + tempChannel.isPlaying = true; + + std::lock_guard lock(MutexLock); + m_pointSounds.emplace_back(tempChannel); + + m_usedObjects++; + } + } + + } + else if (m_gamePadButtons.dpadDown == m_gamePadButtons.RELEASED) + { + if (m_pointSounds.size() > 0) + { + m_pointSounds.back().isPlaying = false; + m_usedObjects--; + } + } + } + else + { + m_gamePadButtons.Reset(); + } + + //Update the point sounds + for (std::vector::iterator it = m_pointSounds.begin(); it != m_pointSounds.end(); it++) + { + switch (it->travelData.travelType) + { + case Linear: + LinearTravel(&(*it)); + break; + case Bounce: + BounceTravel(&(*it)); + break; + case Round: + RoundTravel(&(*it)); + break; + } + + float distance = sqrtf(powf(it->posX, 2.0) + powf(it->posY, 2.0) + powf(it->posZ, 2.0)); + float volume = 1.f - ((distance - CURVE_START) / (CURVE_END - CURVE_START)); + + if (volume < 0) + { + it->volume = 0; + } + else if (volume > 1.f) + { + it->volume = 1.f; + } + else + { + it->volume = volume; + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + auto rect = m_deviceResources->GetOutputSize(); + auto safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + + wchar_t str[256] = { 0 }; + swprintf_s(str, L"Advanced Spatial Playback"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + if (!m_Renderer->IsActive()) + { + swprintf_s(str, L"Spatial Renderer Not Available"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 60; + } + else + { + swprintf_s(str, L"State: %s", ((m_bPlayingSound) ? L"Playing" : L"Stopped")); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L"Use A button to start/stop playback"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L"Use Dpad UP/DOWN to add/remove a sound"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 60; + swprintf_s(str, L"Available Dynamic Objects: %d", m_availableObjects - m_usedObjects); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L"Used Dynamic Objects: %d", m_usedObjects); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L"Total Objects: %d", m_usedObjects + MAX_CHANNELS); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 60; + } + + DrawRoom(Colors::Green); + + for (std::vector::iterator it = m_pointSounds.begin(); it != m_pointSounds.end(); it++) + { + if (it->posZ < 0) + { + DrawSound(it->posX, it->posY, it->posZ, Colors::Blue); + } + } + + DrawListener(Colors::Yellow); + + for (std::vector::iterator it = m_pointSounds.begin(); it != m_pointSounds.end(); it++) + { + if (it->posZ >= 0) + { + DrawSound(it->posX, it->posY, it->posZ, Colors::Blue); + } + } + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_spriteBatch = std::make_unique(context); + + m_states = std::make_unique(device); + + m_batchEffect = std::make_unique(device); + m_batchEffect->SetVertexColorEnabled(true); + + { + void const* shaderByteCode; + size_t byteCodeLength; + + m_batchEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); + + DX::ThrowIfFailed( + device->CreateInputLayout(VertexPositionColor::InputElements, + VertexPositionColor::InputElementCount, + shaderByteCode, byteCodeLength, + m_batchInputLayout.ReleaseAndGetAddressOf()) + ); + } + + m_batch = std::make_unique>(m_deviceResources->GetD3DDeviceContext()); + + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + + CreateDDSTextureFromFile(device, L"callout_circle.DDS", nullptr, m_circle.ReleaseAndGetAddressOf()); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion + + +HRESULT Sample::InitializeSpatialStream(void) +{ + HRESULT hr = S_OK; + + if (!m_Renderer) + { + // Create a new ISAC instance + m_Renderer = Microsoft::WRL::Make(); + // Selects the Default Audio Device + hr = m_Renderer->InitializeAudioDeviceAsync(); + } + + return hr; +} + +bool Sample::LoadBed() +{ + for (UINT32 i = 0; i < MAX_CHANNELS; i++) + { + if (m_bedChannels[i].bufferSize) + { + delete[] m_bedChannels[i].wavBuffer; + } + m_bedChannels[i].bufferSize = 0; + m_bedChannels[i].curBufferLoc = 0; + m_bedChannels[i].volume = 1.f; + } + + m_numChannels = 0; + + HRESULT hr = S_OK; + std::unique_ptr m_waveFile; + DX::WAVData WavData; + LPCWSTR inFile; + int channelCount = 0; + + for (int fileIndex = 0; fileIndex < g_numBedFiles; fileIndex++) + { + inFile = g_bedFileList[fileIndex]; + + hr = DX::LoadWAVAudioFromFileEx(inFile, m_waveFile, WavData); + if (FAILED(hr)) + { + return false; + } + + if ((WavData.wfx->wFormatTag == 1 || WavData.wfx->wFormatTag == 65534) && WavData.wfx->nSamplesPerSec == 48000) + { + m_numChannels += WavData.wfx->nChannels; + + int numSamples = WavData.audioBytes / (2 * WavData.wfx->nChannels); + for (int i = 0; i < WavData.wfx->nChannels; i++) + { + m_bedChannels[channelCount + i].wavBuffer = new char[numSamples * 4]; + m_bedChannels[channelCount + i].bufferSize = numSamples * 4; + } + + float * tempnew; + short * tempdata = (short *)WavData.startAudio; + + for (int i = 0; i < numSamples; i++) + { + for (int j = 0; j < WavData.wfx->nChannels; j++) + { + tempnew = (float *)m_bedChannels[channelCount + j].wavBuffer; + tempnew[i] = (float)tempdata[(i * WavData.wfx->nChannels) + j] / 32768; + } + } + + channelCount += WavData.wfx->nChannels; + } + else if ((WavData.wfx->wFormatTag == 3) && WavData.wfx->nSamplesPerSec == 48000) + { + m_numChannels += WavData.wfx->nChannels; + + int numSamples = WavData.audioBytes / (4 * WavData.wfx->nChannels); + for (int i = 0; i < WavData.wfx->nChannels; i++) + { + m_bedChannels[channelCount + i].wavBuffer = new char[numSamples * 4]; + m_bedChannels[channelCount + i].bufferSize = numSamples * 4; + } + + float * tempnew; + short * tempdata = (short *)WavData.startAudio; + + for (int i = 0; i < numSamples; i++) + { + for (int j = 0; j < WavData.wfx->nChannels; j++) + { + tempnew = (float *)m_bedChannels[j].wavBuffer; + tempnew[i] = (float)tempdata[(i * WavData.wfx->nChannels) + j]; + } + } + + channelCount += WavData.wfx->nChannels; + } + else + { + return false; + } + } + + m_bedChannels[0].objType = AudioObjectType_FrontLeft; + m_bedChannels[1].objType = AudioObjectType_FrontRight; + m_bedChannels[2].objType = AudioObjectType_FrontCenter; + m_bedChannels[3].objType = AudioObjectType_LowFrequency; + m_bedChannels[4].objType = AudioObjectType_BackLeft; + m_bedChannels[5].objType = AudioObjectType_BackRight; + m_bedChannels[6].objType = AudioObjectType_SideLeft; + m_bedChannels[7].objType = AudioObjectType_SideRight; + m_bedChannels[8].objType = AudioObjectType_TopFrontLeft; + m_bedChannels[9].objType = AudioObjectType_TopFrontRight; + m_bedChannels[10].objType = AudioObjectType_TopBackLeft; + m_bedChannels[11].objType = AudioObjectType_TopBackRight; + + return true; +} + +bool Sample::LoadPointFile(LPCWSTR inFile, PointSound* outChannel) +{ + std::unique_ptr m_waveFile; + DX::WAVData WavData; + + outChannel->bufferSize = 0; + outChannel->curBufferLoc = 0; + outChannel->volume = 1.f; + + if (DX::LoadWAVAudioFromFileEx(inFile, m_waveFile, WavData)) + { + return false; + } + + if ((WavData.wfx->wFormatTag == 1 || WavData.wfx->wFormatTag == 65534) && WavData.wfx->nSamplesPerSec == 48000 && WavData.wfx->nChannels == 1) + { + int numSamples = WavData.audioBytes / 2; + outChannel->wavBuffer = new char[numSamples * 4]; + outChannel->bufferSize = numSamples * 4; + + float * tempnew; + short * tempdata = (short *)WavData.startAudio; + + for (int i = 0; i < numSamples; i++) + { + tempnew = (float *)outChannel->wavBuffer; + tempnew[i] = (float)tempdata[i] / 32768; + } + } + else if ((WavData.wfx->wFormatTag == 3) && WavData.wfx->nSamplesPerSec == 48000 && WavData.wfx->nChannels == 1) + { + int numSamples = WavData.audioBytes / 4; + outChannel->wavBuffer = new char[numSamples * 4]; + outChannel->bufferSize = numSamples * 4; + + float * tempnew; + float * tempdata = (float *)WavData.startAudio; + + for (int i = 0; i < numSamples; i++) + { + tempnew = (float *)outChannel->wavBuffer; + tempnew[i] = (float)tempdata[i]; + } + } + else + { + return false; + } + + return true; +} + +void Sample::LinearTravel(PointSound* inSound) +{ + //Travel in one direction until hitting a wall, then reverse + XMVECTOR staringPosition = { inSound->posX, inSound->posY, inSound->posZ }; + XMVECTOR direction = XMLoadFloat3(&inSound->travelData.direction); + XMVECTOR newPoint = XMVectorAdd(XMVectorScale(direction, inSound->travelData.vel), staringPosition); + + if (inSound->travelData.boundingBox.Contains(newPoint) == DISJOINT) + { + //Find the intersection point + float distance = 0; + XMVECTOR newDirection = XMVectorNegate(direction); + inSound->travelData.boundingBox.Intersects(newPoint, newDirection, distance); + XMVECTOR intersectPoint = XMVectorMultiplyAdd(direction, XMVectorReplicate(inSound->travelData.vel - distance), staringPosition); + + //Bounce back the way we came + newPoint = XMVectorAdd(XMVectorScale(newDirection, distance), intersectPoint); + XMStoreFloat3(&inSound->travelData.direction, newDirection); + } + + inSound->posX = XMVectorGetX(newPoint); + inSound->posY = XMVectorGetY(newPoint); + inSound->posZ = XMVectorGetZ(newPoint); +} + +void Sample::BounceTravel(PointSound* inSound) +{ + //Travel in one direction until hitting a wall, then bounce + XMVECTOR staringPosition = { inSound->posX, inSound->posY, inSound->posZ }; + XMVECTOR direction = XMLoadFloat3(&inSound->travelData.direction); + XMVECTOR newPoint = XMVectorAdd(XMVectorScale(direction, inSound->travelData.vel), staringPosition); + + if (inSound->travelData.boundingBox.Contains(newPoint) == DISJOINT) + { + //Find the intersection point + float distance = 0; + XMVECTOR newDirection = XMVectorNegate(direction); + inSound->travelData.boundingBox.Intersects(newPoint, newDirection, distance); + XMVECTOR intersectPoint = XMVectorMultiplyAdd(direction, XMVectorReplicate(inSound->travelData.vel - distance), staringPosition); + + //Build the vector to multiply + XMFLOAT3 tempPoint; + XMStoreFloat3(&tempPoint, intersectPoint); + + float checkPointHigh = inSound->travelData.boundingBox.Center.x + inSound->travelData.boundingBox.Extents.x; + float checkPointLow = inSound->travelData.boundingBox.Center.x - inSound->travelData.boundingBox.Extents.x; + + if (tempPoint.x == checkPointHigh || tempPoint.x == checkPointLow) + { + tempPoint.x = -1.f; + } + else + { + tempPoint.x = 1.f; + } + + checkPointHigh = inSound->travelData.boundingBox.Center.x + inSound->travelData.boundingBox.Extents.x; + checkPointLow = inSound->travelData.boundingBox.Center.x - inSound->travelData.boundingBox.Extents.x; + + if (tempPoint.y == checkPointHigh || tempPoint.y == checkPointLow) + { + tempPoint.y = -1.f; + } + else + { + tempPoint.y = 1.f; + } + + checkPointHigh = inSound->travelData.boundingBox.Center.x + inSound->travelData.boundingBox.Extents.x; + checkPointLow = inSound->travelData.boundingBox.Center.x - inSound->travelData.boundingBox.Extents.x; + + if (tempPoint.z == checkPointHigh || tempPoint.z == checkPointLow) + { + tempPoint.z = -1.f; + } + else + { + tempPoint.z = 1.f; + } + + direction = XMVectorMultiply(direction, XMLoadFloat3(&tempPoint)); + newPoint = XMVectorAdd(XMVectorScale(direction, distance), intersectPoint); + XMStoreFloat3(&inSound->travelData.direction, direction); + } + + inSound->posX = XMVectorGetX(newPoint); + inSound->posY = XMVectorGetY(newPoint); + inSound->posZ = XMVectorGetZ(newPoint); +} + +void Sample::RoundTravel(PointSound* inSound) +{ + //Travel in a cirle around the listener + XMVECTOR start = { inSound->posX, inSound->posY, inSound->posZ }; + XMMATRIX transform = XMMatrixRotationZ(inSound->travelData.vel / inSound->travelData.radius); + XMVECTOR newPoint = XMVector3Transform(start, transform); + inSound->posX = XMVectorGetX(newPoint); + inSound->posY = XMVectorGetY(newPoint); + inSound->posZ = XMVectorGetZ(newPoint); +} diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.h b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.h new file mode 100644 index 0000000000000000000000000000000000000000..7abb108afeba22618a9c251c410de0cf06143f63 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.h @@ -0,0 +1,164 @@ +//-------------------------------------------------------------------------------------- +// SimpleSpatialPlaySoundXDK.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "SpriteFont.h" +#include "ISACRenderer.h" +#include +#include + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +#define MAX_CHANNELS 12 //up to 7.1.4 channels + +enum TravelType { + Linear = 0, + Bounce, + Round +}; + +struct TravelData +{ + TravelType travelType; + float radius; + float vel; + DirectX::XMFLOAT3 direction; + DirectX::BoundingBox boundingBox; +}; + +struct BedChannel +{ + char * wavBuffer; + UINT32 bufferSize; + float volume; + UINT32 curBufferLoc; + Microsoft::WRL::ComPtr object; + AudioObjectType objType; +}; + +struct PointSound +{ + char * wavBuffer; + UINT32 bufferSize; + float volume; + UINT32 curBufferLoc; + float posX; + float posY; + float posZ; + int soundIndex; + Microsoft::WRL::ComPtr object; + TravelData travelData; + bool isPlaying; +}; + +class Sample +{ +#define MAX_CHANNELS 12 //up to 7.1.4 channels + + struct Audiochannel + { + char * wavBuffer; + UINT32 buffersize; + float volume; + UINT32 curBufferLoc; + float PosX; + float PosY; + float PosZ; + + Microsoft::WRL::ComPtr object; + AudioObjectType objType; + + }; + +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // Messages + void OnSuspending(); + void OnResuming(); + + + Microsoft::WRL::ComPtr m_Renderer; + + bool m_bThreadActive; + bool m_bPlayingSound; + int availableObjects; + + BedChannel m_bedChannels[MAX_CHANNELS]; + std::vector m_pointSounds; + int m_numChannels; + std::mutex MutexLock; + int m_availableObjects; + int m_usedObjects; + +private: + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void XM_CALLCONV DrawRoom(DirectX::FXMVECTOR color); + void XM_CALLCONV DrawListener(DirectX::FXMVECTOR color); + void XM_CALLCONV DrawSound(float x, float y, float z, DirectX::FXMVECTOR color); + + bool LoadBed(); + bool LoadPointFile(LPCWSTR inFile, PointSound* outChannel); + + void Sample::LinearTravel(PointSound* inSound); + void Sample::BounceTravel(PointSound* inSound); + void Sample::RoundTravel(PointSound* inSound); + + DirectX::BoundingBox m_boundingBox; + + HRESULT InitializeSpatialStream(void); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + + std::unique_ptr> m_batch; + Microsoft::WRL::ComPtr m_batchInputLayout; + std::unique_ptr m_states; + std::unique_ptr m_batchEffect; + Microsoft::WRL::ComPtr m_circle; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + bool m_fileLoaded; + int m_curFile; + + //worker thread for spatial system + PTP_WORK m_workThread; + + +}; diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.sln b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.sln new file mode 100644 index 0000000000000000000000000000000000000000..bc3374e84f2a54411405c750175f2de5e49effe7 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvancedSpatialSoundsXDK", "AdvancedSpatialSoundsXDK.vcxproj", "{8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Debug|Durango.ActiveCfg = Debug|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Debug|Durango.Build.0 = Debug|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Debug|Durango.Deploy.0 = Debug|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Profile|Durango.ActiveCfg = Profile|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Profile|Durango.Build.0 = Profile|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Profile|Durango.Deploy.0 = Profile|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Release|Durango.ActiveCfg = Release|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Release|Durango.Build.0 = Release|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Release|Durango.Deploy.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.vcxproj b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..d32ce97bedbae6c3193f50f9e3196cb207931a3d --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.vcxproj @@ -0,0 +1,240 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleSpatialPlaySoundXDK + {8d1b958e-aab0-48cf-bd60-c39a7febb662} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + mmdevapi.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + + + + + mmdevapi.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + + + + + MFplat.lib;mmdevapi.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.vcxproj.filters b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..a929327e86f553aaf70c46ef01fef676a7fda708 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/AdvancedSpatialSoundsXDK.vcxproj.filters @@ -0,0 +1,156 @@ + + + + + 58c2a4ad-94cc-46b7-a31b-ca3e072f18b9 + + + 47d8bfa9-7bbd-490c-b646-0d31e8a9317f + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {e4d804ca-14eb-4f67-8112-df83634be576} + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_5.1_mixdown.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_5.1_mixdown.wav new file mode 100644 index 0000000000000000000000000000000000000000..6a0a73ac908fde72b7e5807291198a032d0885fc Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_5.1_mixdown.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_SideSurroundL-R.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_SideSurroundL-R.wav new file mode 100644 index 0000000000000000000000000000000000000000..9d5da9e910849df583f1a7cde117ea36ad0310cc Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_SideSurroundL-R.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_TopFrontL-R.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_TopFrontL-R.wav new file mode 100644 index 0000000000000000000000000000000000000000..20be39e8e04f508d2c76356c558ad0ef00749cc7 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_TopFrontL-R.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_TopRearL-R.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_TopRearL-R.wav new file mode 100644 index 0000000000000000000000000000000000000000..e46c0f605bd9a103faeb90759d5b74065b30b362 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Jungle_RainThunder_TopRearL-R.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Logo.png b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7e704a106b99487be0f1eded426e6c5a2c65a9 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/Logo.png differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_height_birdHawk01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_height_birdHawk01.wav new file mode 100644 index 0000000000000000000000000000000000000000..a7364ebfc7d58b8559c634e89f0cc7050d06237a Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_height_birdHawk01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_height_birdLoon01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_height_birdLoon01.wav new file mode 100644 index 0000000000000000000000000000000000000000..4d58b3c4128fd8c62162acf644a9b5e9dc2689ce Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_height_birdLoon01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_BirdFlap01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_BirdFlap01.wav new file mode 100644 index 0000000000000000000000000000000000000000..baa63ab9b1f23b1ae5d5ad396f947281abf38d59 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_BirdFlap01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_Fly01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_Fly01.wav new file mode 100644 index 0000000000000000000000000000000000000000..1189abd14de19a163cabf23f20863c72b488d62b Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_Fly01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_Fly02.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_Fly02.wav new file mode 100644 index 0000000000000000000000000000000000000000..93183c57e2f12a54e55dab7aec933553348a16b1 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_Fly02.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdFlicker01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdFlicker01.wav new file mode 100644 index 0000000000000000000000000000000000000000..8fd0a8f2de544dd4f8b4120613a6051425c724d7 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdFlicker01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdFlycatcher01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdFlycatcher01.wav new file mode 100644 index 0000000000000000000000000000000000000000..2ec6b842a5f2bb6e78756d885c8e9c0159c03405 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdFlycatcher01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLark01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLark01.wav new file mode 100644 index 0000000000000000000000000000000000000000..a2fbe43fa25d66c3c53f85013f5265602bdbd1ba Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLark01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop01.wav new file mode 100644 index 0000000000000000000000000000000000000000..255e78a35183c1feec8a5ac0265b1e777e87e8a7 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop02.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop02.wav new file mode 100644 index 0000000000000000000000000000000000000000..fc06eef5691f6b1c9500e5b9654857736bc14c9b Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop02.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop03.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop03.wav new file mode 100644 index 0000000000000000000000000000000000000000..ab61b89e953751777b53f248037a4b064e4d4250 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop03.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop04.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop04.wav new file mode 100644 index 0000000000000000000000000000000000000000..e17e32e1610f71b7f334d642153a679fb23597e8 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop04.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop05.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop05.wav new file mode 100644 index 0000000000000000000000000000000000000000..e4e33e476f7155191633c777ae4f905e528edb90 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop05.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop06.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop06.wav new file mode 100644 index 0000000000000000000000000000000000000000..7ffc90af83125d5d996fe2d8b80a06e5eb22ff58 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdLoop06.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdSparrow01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdSparrow01.wav new file mode 100644 index 0000000000000000000000000000000000000000..dd83fedcf8d089428f58a389fb3a9f2a2fa79046 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdSparrow01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdSparrow02.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdSparrow02.wav new file mode 100644 index 0000000000000000000000000000000000000000..25eefff36fc30e5ba1df4b8c3819d8b0bf4ad546 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdSparrow02.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdWarbler01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdWarbler01.wav new file mode 100644 index 0000000000000000000000000000000000000000..c0b20620de62c61ba196028080e3ec62e209bc1a Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_moving_birdWarbler01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_cicada01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_cicada01.wav new file mode 100644 index 0000000000000000000000000000000000000000..e965bbbb09e42b05a74ab5655420546d3ddccdb7 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_cicada01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_grasshopper01.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_grasshopper01.wav new file mode 100644 index 0000000000000000000000000000000000000000..19e0cbaf5c996286184d98556d181d9c1c22d5c2 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_grasshopper01.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_grasshopper02.wav b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_grasshopper02.wav new file mode 100644 index 0000000000000000000000000000000000000000..a3f36da014448071145bedcc7c892b19df4deade Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SFX_stationary_grasshopper02.wav differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SmallLogo.png b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..98b09d91991638282fc2426bbfd4a517733ff15a Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SmallLogo.png differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SplashScreen.png b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..c352b156fd090a57aec7da81b3b19a3fb5888b43 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/SplashScreen.png differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/StoreLogo.png b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..315472e10b9d380e509b2f041ea9ace5f994f5d2 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/StoreLogo.png differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/WideLogo.png b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c70f68e2c59214e0ff54844ccd8ae5e955826e10 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Assets/WideLogo.png differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/DeviceResources.cpp b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/DeviceResources.h b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/ISACRenderer.cpp b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/ISACRenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e2e967189d7718cacaaf31bc51b705f9297c21c --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/ISACRenderer.cpp @@ -0,0 +1,186 @@ +//-------------------------------------------------------------------------------------- +// +// ISACRenderer.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +#include "pch.h" +#include "ISACRenderer.h" + +using namespace Windows::Media::Devices; + +using Microsoft::WRL::ComPtr; + +// +// ISACRenderer() +// +ISACRenderer::ISACRenderer() : + + m_SpatialAudioClient( nullptr ), + m_SpatialAudioStream( nullptr ), + m_ISACrenderstate( RenderState::Inactive ), + m_bufferCompletionEvent( NULL ) +{ + +} + +// +// ~ISACRenderer() +// +ISACRenderer::~ISACRenderer() +{ +} + +// +// InitializeAudioDeviceAsync() +// +// Activates the default audio renderer on a asynchronous callback thread. This needs +// to be called from the main UI thread. +// +HRESULT ISACRenderer::InitializeAudioDeviceAsync() +{ + ComPtr asyncOp; + HRESULT hr = S_OK; + + // Get a string representing the Default Audio Device Renderer + m_DeviceIdString = MediaDevice::GetDefaultAudioRenderId( Windows::Media::Devices::AudioDeviceRole::Default ); + + EnableSpatialAudio(); + + // This call must be made on the main UI thread. Async operation will call back to + // IActivateAudioInterfaceCompletionHandler::ActivateCompleted, which must be an agile interface implementation + hr = ActivateAudioInterfaceAsync(m_DeviceIdString->Data(), __uuidof(ISpatialAudioClient), nullptr, this, &asyncOp); + + if (FAILED( hr )) + { + m_ISACrenderstate = RenderState::Inactive; + } + + return hr; +} + +//When Spatial dynamic object count changes, note new number of max available objects +HRESULT ISACRenderer::OnAvailableDynamicObjectCountChange(ISpatialAudioObjectRenderStreamBase *sender, LONGLONG hnsComplianceDeadlineTime, UINT32 availableDynamicObjectCountChange) +{ + sender; + hnsComplianceDeadlineTime; + + m_MaxDynamicObjects = availableDynamicObjectCountChange; + return S_OK; +} + +// +// ActivateCompleted() +// +// Callback implementation of ActivateAudioInterfaceAsync function. This will be called on MTA thread +// when results of the activation are available. +// +HRESULT ISACRenderer::ActivateCompleted( IActivateAudioInterfaceAsyncOperation *operation ) +{ + HRESULT hr = S_OK; + HRESULT hrActivateResult = S_OK; + ComPtr punkAudioInterface = nullptr; + + // Check for a successful activation result + hr = operation->GetActivateResult( &hrActivateResult, &punkAudioInterface ); + if (SUCCEEDED( hr ) && SUCCEEDED( hrActivateResult )) + { + // Get the pointer for the Audio Client + punkAudioInterface.Get()->QueryInterface( IID_PPV_ARGS(&m_SpatialAudioClient) ); + if( nullptr == m_SpatialAudioClient) + { + hr = E_FAIL; + goto exit; + } + + // Check the available rendering formats + ComPtr audioObjectFormatEnumerator; + hr = m_SpatialAudioClient->GetSupportedAudioObjectFormatEnumerator(&audioObjectFormatEnumerator); + + // WavFileIO is helper class to read WAV file + WAVEFORMATEX* objectFormat = nullptr; + UINT32 audioObjectFormatCount; + hr = audioObjectFormatEnumerator->GetCount(&audioObjectFormatCount); // There is at least one format that the API accept + if (audioObjectFormatCount == 0) + { + hr = E_FAIL; + goto exit; + } + + // Select the most favorable format, first one + hr = audioObjectFormatEnumerator->GetFormat(0, &objectFormat); + + // Create the event that will be used to signal the client for more data + m_bufferCompletionEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + // Define the object mask for the Spatial bed - in this case 7.1.4 + AudioObjectType objectmask = + AudioObjectType_FrontLeft | + AudioObjectType_FrontRight | + AudioObjectType_FrontCenter | + AudioObjectType_LowFrequency | + AudioObjectType_SideLeft | + AudioObjectType_SideRight | + AudioObjectType_BackLeft | + AudioObjectType_BackRight | + AudioObjectType_TopFrontLeft | + AudioObjectType_TopFrontRight | + AudioObjectType_TopBackLeft | + AudioObjectType_TopBackRight; + + // Determine maximum available dynamic objects + m_SpatialAudioClient->GetMaxDynamicObjectCount(&m_MaxDynamicObjects); + + // Set the activation parameters for the Spatial stream + SpatialAudioObjectRenderStreamActivationParams activationparams = + { + objectFormat, + objectmask, + m_MaxDynamicObjects, + m_MaxDynamicObjects, + AudioCategory_GameEffects, + m_bufferCompletionEvent, + nullptr + }; + + PROPVARIANT activateParams; + PropVariantInit(&activateParams); + activateParams.vt = VT_BLOB; + activateParams.blob.cbSize = sizeof(activationparams); + activateParams.blob.pBlobData = reinterpret_cast(&activationparams); + + // Activate the spatial stream + hr = m_SpatialAudioClient->ActivateSpatialAudioStream(&activateParams, __uuidof(m_SpatialAudioStream), &m_SpatialAudioStream); + if (FAILED(hr)) + { + hr = E_FAIL; + goto exit; + } + + // Start streaming / rendering  + hr = m_SpatialAudioStream->Start(); + if (FAILED(hr)) + { + hr = E_FAIL; + goto exit; + } + + m_ISACrenderstate = RenderState::Active; + + } + +exit: + + if (FAILED( hr )) + { + m_ISACrenderstate = RenderState::Inactive; + } + + // Need to return S_OK + return S_OK; +} + + diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/ISACRenderer.h b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/ISACRenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..fc59a747c28eb2104af6c2fc62e303cf0110f23f --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/ISACRenderer.h @@ -0,0 +1,50 @@ +//-------------------------------------------------------------------------------------- +// ISACRenderer.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "SpatialAudioClient.h" +#include + +#pragma once + + // Primary ISAC Renderering Class + class ISACRenderer : + public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::ClassicCom >, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler > + { + public: + enum RenderState { + Inactive = 0, + Active, + Resetting + }; + + ISACRenderer(); + + HRESULT InitializeAudioDeviceAsync(); + bool IsActive() { return m_ISACrenderstate == RenderState::Active; }; + bool IsResetting() { return m_ISACrenderstate == RenderState::Resetting; } + void Reset() { m_ISACrenderstate = RenderState::Resetting; } + UINT32 GetMaxDynamicObjects() { return m_MaxDynamicObjects; } + + STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation ); + STDMETHOD(OnAvailableDynamicObjectCountChange)(ISpatialAudioObjectRenderStreamBase *sender, LONGLONG hnsComplianceDeadlineTime, UINT32 availableDynamicObjectCountChange); + + Microsoft::WRL::ComPtr m_SpatialAudioStream; + + HANDLE m_bufferCompletionEvent; + private: + ~ISACRenderer(); + + Platform::String^ m_DeviceIdString; + RenderState m_ISACrenderstate; + UINT32 m_MaxDynamicObjects; + + Microsoft::WRL::ComPtr m_SpatialAudioClient; + + }; + + + diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Main.cpp b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c0eafe3ec95cce481e83acb2ed7b7a3878c7d82 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "AdvancedSpatialSoundsXDK.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH + 1] = {}; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Package.appxmanifest b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..21bf8811d8f57b61d0bc551c4a1d2c0dfac3eb8d --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + AdvancedSpatialSoundsXDK + Xbox Advanced Technology Group + Assets\StoreLogo.png + AdvancedSpatialSoundsXDK + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Readme.docx b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..3f2dd25f3dc3529b65826cd754b48eed5086af63 Binary files /dev/null and b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Readme.docx differ diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/StepTimer.h b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Telemetry.h b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/pch.cpp b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Audio/AdvancedSpatialSoundsXDK/pch.h b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..a928a0395126cd173e853b312e6d09e16901360d --- /dev/null +++ b/XDKSamples/Audio/AdvancedSpatialSoundsXDK/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "Effects.h" +#include "CommonStates.h" +#include "PrimitiveBatch.h" +#include "VertexTypes.h" +#include "DDSTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Audio/SimplePlaySound/Assets/Logo.png b/XDKSamples/Audio/SimplePlaySound/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..685da49f12563e956b29413f22e245e49fbfc33f Binary files /dev/null and b/XDKSamples/Audio/SimplePlaySound/Assets/Logo.png differ diff --git a/XDKSamples/Audio/SimplePlaySound/Assets/SmallLogo.png b/XDKSamples/Audio/SimplePlaySound/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..9b2bd39c9704690c022db78f955173c87dcc14f9 Binary files /dev/null and b/XDKSamples/Audio/SimplePlaySound/Assets/SmallLogo.png differ diff --git a/XDKSamples/Audio/SimplePlaySound/Assets/SplashScreen.png b/XDKSamples/Audio/SimplePlaySound/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..f622ca7e90f953a63d16aa0bc6d15536deff8803 Binary files /dev/null and b/XDKSamples/Audio/SimplePlaySound/Assets/SplashScreen.png differ diff --git a/XDKSamples/Audio/SimplePlaySound/Assets/StoreLogo.png b/XDKSamples/Audio/SimplePlaySound/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Audio/SimplePlaySound/Assets/StoreLogo.png differ diff --git a/XDKSamples/Audio/SimplePlaySound/Assets/WideLogo.png b/XDKSamples/Audio/SimplePlaySound/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..4f1fa8f8f1987fbc4d18346cdc054f9b4dbc8725 Binary files /dev/null and b/XDKSamples/Audio/SimplePlaySound/Assets/WideLogo.png differ diff --git a/XDKSamples/Audio/SimplePlaySound/DeviceResources.cpp b/XDKSamples/Audio/SimplePlaySound/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/Audio/SimplePlaySound/DeviceResources.h b/XDKSamples/Audio/SimplePlaySound/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/Audio/SimplePlaySound/Main.cpp b/XDKSamples/Audio/SimplePlaySound/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9b30410f4e8b312538d45df68deece594da02b9 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimplePlaySound.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/Audio/SimplePlaySound/Package.appxmanifest b/XDKSamples/Audio/SimplePlaySound/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..3e2702d498a8633b694bf6483eb1341ba911bcad --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimplePlaySound + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimplePlaySound + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Audio/SimplePlaySound/Readme.docx b/XDKSamples/Audio/SimplePlaySound/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..d3a18bd924a7d62111337c1c9780137c9fd1ee20 Binary files /dev/null and b/XDKSamples/Audio/SimplePlaySound/Readme.docx differ diff --git a/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.cpp b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f58af8072997457109764843d326fc22ca3c160 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.cpp @@ -0,0 +1,334 @@ +//-------------------------------------------------------------------------------------- +// SimplePlaySound.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimplePlaySound.h" + +#include "WAVFileReader.h" + +static const wchar_t* g_FileList[] = { + L"71_setup_sweep_xbox.wav", + L"musicmono.wav", + L"musicmono_xma.wav", + L"musicmono_adpcm.wav", + L"musicmono_xwma.wav", + L"sine.wav", + nullptr +}; + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0), + m_pMasteringVoice(nullptr), + m_pSourceVoice(nullptr), + m_currentFile(0), + m_xmaMemory(nullptr) +{ + // Renders only 2D, so no need for a depth buffer. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + // Initialize XAudio2 objects + DX::ThrowIfFailed(XAudio2Create(m_pXAudio2.GetAddressOf(), 0)); + +#ifdef _DEBUG + // Enable debugging features + XAUDIO2_DEBUG_CONFIGURATION debug = { 0 }; + debug.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS; + debug.BreakMask = XAUDIO2_LOG_ERRORS; + m_pXAudio2->SetDebugConfiguration(&debug, 0); +#endif + + DX::ThrowIfFailed(m_pXAudio2->CreateMasteringVoice(&m_pMasteringVoice)); + + // Start playing the first file + m_currentFile = 0; + Play(g_FileList[m_currentFile]); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + + // Check to see if buffer has finished playing, then move on to next sound + XAUDIO2_VOICE_STATE state; + m_pSourceVoice->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED); + if (state.BuffersQueued == 0) + { + m_pSourceVoice->DestroyVoice(); + + if (g_FileList[++m_currentFile] == nullptr) + { + m_currentFile = 0; + } + + Play(g_FileList[m_currentFile]); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(1920, 1080); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + wchar_t str[128] = { 0 }; + swprintf_s(str, L"Playing: %ls", g_FileList[m_currentFile]); + + m_font->DrawString(m_spriteBatch.get(), str, pos); + + if (!m_waveDesc.empty()) + { + pos.y += m_font->GetLineSpacing(); + + m_font->DrawString(m_spriteBatch.get(), m_waveDesc.c_str(), pos); + } + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + // Don't need to clear color as the sample draws a fullscreen image background + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); + + // Suspend audio engine + m_pXAudio2->StopEngine(); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + + // Resume audio engine + m_pXAudio2->StartEngine(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion + +void Sample::Play(const wchar_t* szFilename) +{ + // Free any audio data from previous play (source voice must not be playing from it!) + m_waveFile.reset(); + + if (m_xmaMemory) + { + ApuFree(m_xmaMemory); + m_xmaMemory = nullptr; + } + + // Load audio data from disk + DX::WAVData waveData; + DX::ThrowIfFailed(DX::LoadWAVAudioFromFileEx(szFilename, m_waveFile, waveData)); + + // Set up text description + m_waveDesc.clear(); + + uint32_t tag = DX::GetFormatTag(waveData.wfx); + switch (tag) + { + case WAVE_FORMAT_ADPCM: + m_waveDesc = L"ADPCM"; + break; + + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + m_waveDesc = L"xWMA"; + break; + + case WAVE_FORMAT_PCM: + m_waveDesc = L"PCM"; + break; + + case WAVE_FORMAT_XMA2: + m_waveDesc = L"XMA2"; + break; + } + + { + wchar_t buff[64]; + swprintf_s(buff, L" (%u channels, %u bits, %u samples, %zu ms duration)", + waveData.wfx->nChannels, + waveData.wfx->wBitsPerSample, + waveData.wfx->nSamplesPerSec, + waveData.GetSampleDurationMS()); + + m_waveDesc += buff; + + if (waveData.loopLength > 0) + { + m_waveDesc += L" [loop point]"; + } + } + + // Create the source voice + DX::ThrowIfFailed(m_pXAudio2->CreateSourceVoice(&m_pSourceVoice, waveData.wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO)); + + // Submit wave data + XAUDIO2_BUFFER buffer = { 0 }; + buffer.pAudioData = waveData.startAudio; + buffer.Flags = XAUDIO2_END_OF_STREAM; // Indicates all the audio data is being submitted at once + buffer.AudioBytes = waveData.audioBytes; + + if (waveData.loopLength > 0) + { + buffer.LoopBegin = waveData.loopStart; + buffer.LoopLength = waveData.loopLength; + buffer.LoopCount = 1; // We'll just assume we play the loop twice + } + + if (tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3) + { + // + // xWMA includes seek tables which must be provided + // + XAUDIO2_BUFFER_WMA xwmaBuffer = { 0 }; + xwmaBuffer.pDecodedPacketCumulativeBytes = waveData.seek; + xwmaBuffer.PacketCount = waveData.seekCount; + + DX::ThrowIfFailed(m_pSourceVoice->SubmitSourceBuffer(&buffer, &xwmaBuffer)); + } + else if (tag == WAVE_FORMAT_XMA2) + { + // + // To play XMA2 data, we need the audio data in APU memory rather than system memory + // + DX::ThrowIfFailed(ApuAlloc(&m_xmaMemory, nullptr, static_cast(waveData.audioBytes), SHAPE_XMA_INPUT_BUFFER_ALIGNMENT)); + + memcpy(m_xmaMemory, waveData.startAudio, waveData.audioBytes); + + buffer.pAudioData = static_cast( m_xmaMemory ); + DX::ThrowIfFailed(m_pSourceVoice->SubmitSourceBuffer(&buffer)); + } + else + { + DX::ThrowIfFailed(m_pSourceVoice->SubmitSourceBuffer(&buffer)); + } + + // Start playing the voice + DX::ThrowIfFailed(m_pSourceVoice->Start()); +} + diff --git a/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.h b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.h new file mode 100644 index 0000000000000000000000000000000000000000..9f2cd83de7106af2d61d6c258d6cdaefd866c785 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// SimplePlaySound.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void Play(const wchar_t* szFilename); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // Render objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + + Microsoft::WRL::ComPtr m_background; + + // Audio objects. + Microsoft::WRL::ComPtr m_pXAudio2; + IXAudio2MasteringVoice* m_pMasteringVoice; + IXAudio2SourceVoice* m_pSourceVoice; + int m_currentFile; + std::unique_ptr m_waveFile; + std::wstring m_waveDesc; + + void* m_xmaMemory; +}; diff --git a/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.sln b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.sln new file mode 100644 index 0000000000000000000000000000000000000000..21a36df1c23f489bcf983d073d9908392cc40f0c --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimplePlaySound", "SimplePlaySound.vcxproj", "{14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Debug|Durango.ActiveCfg = Debug|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Debug|Durango.Build.0 = Debug|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Debug|Durango.Deploy.0 = Debug|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Profile|Durango.ActiveCfg = Profile|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Profile|Durango.Build.0 = Profile|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Profile|Durango.Deploy.0 = Profile|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Release|Durango.ActiveCfg = Release|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Release|Durango.Build.0 = Release|Durango + {14C845E9-3ADE-4506-BD88-F6BDAA9AEB76}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.vcxproj b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..554b094e0c4c3ca4f9daf1ad496d2397b632c17a --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.vcxproj @@ -0,0 +1,223 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimplePlaySound + {14c845e9-3ade-4506-bd88-f6bdaa9aeb76} + en-US + Win32Proj + title + + v140 + 11.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + acphal.lib;xaudio2.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + acphal.lib;xaudio2.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + acphal.lib;xaudio2.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.vcxproj.filters b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..081cc66c644d714d9dba1d2d61df7fd2f09bd0cb --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/SimplePlaySound.vcxproj.filters @@ -0,0 +1,91 @@ + + + + + bcf1d4b1-b20f-40d4-8fbb-50397772cd42 + + + 87ca9165-96c6-4822-8a5a-dacd83ec50b0 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {4aae28c9-8be0-46cf-89eb-e15f0404dafc} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/Audio/SimplePlaySound/StepTimer.h b/XDKSamples/Audio/SimplePlaySound/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Audio/SimplePlaySound/Telemetry.h b/XDKSamples/Audio/SimplePlaySound/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Audio/SimplePlaySound/pch.cpp b/XDKSamples/Audio/SimplePlaySound/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Audio/SimplePlaySound/pch.h b/XDKSamples/Audio/SimplePlaySound/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..2e8d773b0c21853457d53e6468c8025c99092bf5 --- /dev/null +++ b/XDKSamples/Audio/SimplePlaySound/pch.h @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "DDSTextureLoader.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +#include + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/Logo.png b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..685da49f12563e956b29413f22e245e49fbfc33f Binary files /dev/null and b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/Logo.png differ diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/SmallLogo.png b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..9b2bd39c9704690c022db78f955173c87dcc14f9 Binary files /dev/null and b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/SmallLogo.png differ diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/SplashScreen.png b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..f622ca7e90f953a63d16aa0bc6d15536deff8803 Binary files /dev/null and b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/SplashScreen.png differ diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/StoreLogo.png b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/StoreLogo.png differ diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/WideLogo.png b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..4f1fa8f8f1987fbc4d18346cdc054f9b4dbc8725 Binary files /dev/null and b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Assets/WideLogo.png differ diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/DeviceResources.cpp b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/DeviceResources.h b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/ISACRenderer.cpp b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/ISACRenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..206603611ed4968c906f33a6894abaf1216b81e9 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/ISACRenderer.cpp @@ -0,0 +1,172 @@ +//-------------------------------------------------------------------------------------- +// +// ISACRenderer.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +#include "pch.h" +#include "ISACRenderer.h" + +using namespace Windows::Media::Devices; +using Microsoft::WRL::ComPtr; + +// +// ISACRenderer() +// +ISACRenderer::ISACRenderer() : + + m_SpatialAudioClient( nullptr ), + m_SpatialAudioStream( nullptr ), + m_ISACrenderstate( RenderState::Inactive ), + m_bufferCompletionEvent( NULL ) +{ + +} + +// +// ~ISACRenderer() +// +ISACRenderer::~ISACRenderer() +{ +} + +// +// InitializeAudioDeviceAsync() +// +// Activates the default audio renderer on a asynchronous callback thread. This needs +// to be called from the main UI thread. +// +HRESULT ISACRenderer::InitializeAudioDeviceAsync() +{ + ComPtr asyncOp; + HRESULT hr = S_OK; + + // Get a string representing the Default Audio Device Renderer + m_DeviceIdString = MediaDevice::GetDefaultAudioRenderId( Windows::Media::Devices::AudioDeviceRole::Default ); + + EnableSpatialAudio(); + + // This call must be made on the main UI thread. Async operation will call back to + // IActivateAudioInterfaceCompletionHandler::ActivateCompleted, which must be an agile interface implementation + hr = ActivateAudioInterfaceAsync(m_DeviceIdString->Data(), __uuidof(ISpatialAudioClient), nullptr, this, &asyncOp); + + if (FAILED( hr )) + { + m_ISACrenderstate = RenderState::Inactive; + } + + return hr; +} + +// +// ActivateCompleted() +// +// Callback implementation of ActivateAudioInterfaceAsync function. This will be called on MTA thread +// when results of the activation are available. +// +HRESULT ISACRenderer::ActivateCompleted( IActivateAudioInterfaceAsyncOperation *operation ) +{ + HRESULT hr = S_OK; + HRESULT hrActivateResult = S_OK; + ComPtr punkAudioInterface = nullptr; + + // Check for a successful activation result + hr = operation->GetActivateResult( &hrActivateResult, &punkAudioInterface ); + if (SUCCEEDED( hr ) && SUCCEEDED( hrActivateResult )) + { + // Get the pointer for the Audio Client + punkAudioInterface.Get()->QueryInterface( IID_PPV_ARGS(&m_SpatialAudioClient) ); + if( nullptr == m_SpatialAudioClient) + { + hr = E_FAIL; + goto exit; + } + + // Check the available rendering formats + ComPtr audioObjectFormatEnumerator; + hr = m_SpatialAudioClient->GetSupportedAudioObjectFormatEnumerator(&audioObjectFormatEnumerator); + + // WavFileIO is helper class to read WAV file + WAVEFORMATEX* objectFormat = nullptr; + UINT32 audioObjectFormatCount; + hr = audioObjectFormatEnumerator->GetCount(&audioObjectFormatCount); // There is at least one format that the API accept + if (audioObjectFormatCount == 0) + { + hr = E_FAIL; + goto exit; + } + + // Select the most favorable format, first one + hr = audioObjectFormatEnumerator->GetFormat(0, &objectFormat); + + // Create the event that will be used to signal the client for more data + m_bufferCompletionEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + // Define the object mask for the Spatial bed - in this case 7.1.4 + AudioObjectType objectmask = + AudioObjectType_FrontLeft | + AudioObjectType_FrontRight | + AudioObjectType_FrontCenter | + AudioObjectType_LowFrequency | + AudioObjectType_SideLeft | + AudioObjectType_SideRight | + AudioObjectType_BackLeft | + AudioObjectType_BackRight | + AudioObjectType_TopFrontLeft | + AudioObjectType_TopFrontRight | + AudioObjectType_TopBackLeft | + AudioObjectType_TopBackRight; + + // Set the activation parameters for the Spatial stream + SpatialAudioObjectRenderStreamActivationParams activationparams = + { + objectFormat, + objectmask, + 0, //zero dynamic objects needed + 0, //zero dynamic objects needed + AudioCategory_GameEffects, + m_bufferCompletionEvent, + nullptr + }; + + PROPVARIANT activateParams; + PropVariantInit(&activateParams); + activateParams.vt = VT_BLOB; + activateParams.blob.cbSize = sizeof(activationparams); + activateParams.blob.pBlobData = reinterpret_cast(&activationparams); + + // Activate the spatial stream + hr = m_SpatialAudioClient->ActivateSpatialAudioStream(&activateParams, __uuidof(m_SpatialAudioStream), &m_SpatialAudioStream); + if (FAILED(hr)) + { + hr = E_FAIL; + goto exit; + } + + // Start streaming / rendering  + hr = m_SpatialAudioStream->Start(); + if (FAILED(hr)) + { + hr = E_FAIL; + goto exit; + } + + m_ISACrenderstate = RenderState::Active; + + } + +exit: + + if (FAILED( hr )) + { + m_ISACrenderstate = RenderState::Inactive; + } + + // Need to return S_OK + return S_OK; +} + + diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/ISACRenderer.h b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/ISACRenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..9b6aa2d0a27f1bfac7da5352f0574bb7423123eb --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/ISACRenderer.h @@ -0,0 +1,47 @@ +//-------------------------------------------------------------------------------------- +// ISACRenderer.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "SpatialAudioClient.h" +#include + +#pragma once + + // Primary ISAC Renderering Class + class ISACRenderer : + public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::ClassicCom >, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler > + { + public: + enum RenderState { + Inactive = 0, + Active, + Resetting + }; + + ISACRenderer(); + + HRESULT InitializeAudioDeviceAsync(); + bool IsActive() { return m_ISACrenderstate == RenderState::Active; }; + bool IsResetting() { return m_ISACrenderstate == RenderState::Resetting; } + void Reset() { m_ISACrenderstate = RenderState::Resetting; } + + STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation ); + + Microsoft::WRL::ComPtr m_SpatialAudioStream; + + HANDLE m_bufferCompletionEvent; + private: + ~ISACRenderer(); + + Platform::String^ m_DeviceIdString; + RenderState m_ISACrenderstate; + + Microsoft::WRL::ComPtr m_SpatialAudioClient; + + }; + + + diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Main.cpp b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab1ddda8de822d1e2f5fc98f4d44a03e83bb2e96 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleSpatialPlaySoundXDK.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH + 1] = {}; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Package.appxmanifest b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..852fc1734e8ddd1fde04cb8a4b8ea99a4c5b85eb --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleSpatialPlaySoundXDK + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleSpatialPlaySoundXDK + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Readme.docx b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..56cf3b1c33125ddf91053a34202f0c1afc4f2123 Binary files /dev/null and b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Readme.docx differ diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.cpp b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40b47fd003918c8e877dfb374a7a424ebbad80d6 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.cpp @@ -0,0 +1,569 @@ +//-------------------------------------------------------------------------------------- +// SimpleSpatialPlaySoundXDK.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleSpatialPlaySoundXDK.h" +#include "WAVFileReader.h" +#include "ATGColors.h" + +static const LPCWSTR g_FileList[] = { + L"Jungle_RainThunder_mix714.wav", + L"ChannelIDs714.wav", + nullptr +}; + +static const int numFiles = 2; + +using namespace DirectX; + + +using Microsoft::WRL::ComPtr; + +VOID CALLBACK SpatialWorkCallback(_Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context, _Inout_ PTP_WORK Work) +{ + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + Sample * Sink = (Sample *)Context; + Work; + Instance; + + while (Sink->m_bThreadActive) + { + while (Sink->m_bPlayingSound && Sink->m_Renderer->IsActive()) + { + // Wait for a signal from the audio-engine to start the next processing pass + if (WaitForSingleObject(Sink->m_Renderer->m_bufferCompletionEvent, 100) != WAIT_OBJECT_0) + { + //make a call to stream to see why we didn't get a signal after 100ms + hr = Sink->m_Renderer->m_SpatialAudioStream->Reset(); + + //if we have a stream error, set the renderer state to reset + if (hr != S_OK) + { + Sink->m_Renderer->Reset(); + } + continue; + } + + UINT32 frameCount; + UINT32 availableObjectCount; + + + // Begin the process of sending object data and metadata + // Get the number of active object that can be used to send object-data + // Get the number of frame count that each buffer be filled with  + hr = Sink->m_Renderer->m_SpatialAudioStream->BeginUpdatingAudioObjects( + &availableObjectCount, + &frameCount); + + //if we have a stream error, set the renderer state to reset + if (hr != S_OK) + { + Sink->m_Renderer->Reset(); + } + + Sink->availableObjects = availableObjectCount; + + for (int chan = 0; chan < MAX_CHANNELS; chan++) + { + //Activate the object if not yet done + if (Sink->WavChannels[chan].object == nullptr) + { + // If this method called more than activeObjectCount times + // It will fail with this error HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) + hr = Sink->m_Renderer->m_SpatialAudioStream->ActivateSpatialAudioObject( + Sink->WavChannels[chan].objType, + &Sink->WavChannels[chan].object); + if (FAILED(hr)) + { + continue; + } + + } + + //Get the object buffer + BYTE* buffer = nullptr; + UINT32 bytecount; + hr = Sink->WavChannels[chan].object->GetBuffer(&buffer, &bytecount); + if (FAILED(hr)) + { + continue; + } + + Sink->WavChannels[chan].object->SetVolume(Sink->WavChannels[chan].volume); + + UINT32 readsize = bytecount; + + for (UINT32 i = 0; i < readsize; i++) + { + UINT32 fileLoc = Sink->WavChannels[chan].curBufferLoc; + if (chan < Sink->numChannels) + { + buffer[i] = Sink->WavChannels[chan].wavBuffer[fileLoc]; + } + else + { + buffer[i] = 0; + } + + Sink->WavChannels[chan].curBufferLoc++; + if (Sink->WavChannels[chan].curBufferLoc == Sink->WavChannels[chan].buffersize) + { + Sink->WavChannels[chan].curBufferLoc = 0; + } + + + } + } + + // Let the audio-engine know that the object data are available for processing now + hr = Sink->m_Renderer->m_SpatialAudioStream->EndUpdatingAudioObjects(); + if (FAILED(hr)) + { + Sink->m_Renderer->Reset(); + continue; + } + } + } + +} + + + + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(); + m_fileLoaded = false; + m_Renderer = nullptr; + m_bThreadActive = false; + m_bPlayingSound = false; + m_curFile = 0; +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + InitializeSpatialStream(); + + SetChannelPosVolumes(); + + + for (UINT32 i = 0; i < MAX_CHANNELS; i++) + { + WavChannels[i].buffersize = 0; + WavChannels[i].curBufferLoc = 0; + WavChannels[i].object = nullptr; + + } + + m_fileLoaded = LoadFile(g_FileList[m_curFile]); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + elapsedTime; + + //Are we resetting the renderer? This will happen if we get an invalid stream + // which can happen when render mode changes or device changes + if (m_Renderer->IsResetting()) + { + //clear out renderer + m_Renderer == NULL; + + // Create a new ISAC instance + m_Renderer = Microsoft::WRL::Make(); + + // Initialize Default Audio Device + m_Renderer->InitializeAudioDeviceAsync(); + + //Reset all the Objects that were being used + for (int chan = 0; chan < MAX_CHANNELS; chan++) + { + WavChannels[chan].object = nullptr; + } + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_gamePadButtons.a == m_gamePadButtons.RELEASED) + { + //if we have an active renderer + if (m_Renderer && m_Renderer->IsActive()) + { + //Start spatial worker thread + if (!m_bThreadActive) + { + //reload file to start again + m_fileLoaded = LoadFile(g_FileList[m_curFile]); + //startup spatial thread + m_bThreadActive = true; + m_bPlayingSound = true; + m_workThread = CreateThreadpoolWork(SpatialWorkCallback, this, nullptr); + SubmitThreadpoolWork(m_workThread); + } + else + { + //stop and shutdown spatial worker thread + m_bThreadActive = false; + m_bPlayingSound = false; + WaitForThreadpoolWorkCallbacks(m_workThread, FALSE); + CloseThreadpoolWork(m_workThread); + } + } + } + else if (m_gamePadButtons.b == m_gamePadButtons.RELEASED) + { + //if we have an active renderer + if (m_Renderer && m_Renderer->IsActive()) + { + //if spatial thread active and playing, shutdown and start new file + if (m_bThreadActive && m_bPlayingSound) + { + m_bThreadActive = false; + m_bPlayingSound = false; + WaitForThreadpoolWorkCallbacks(m_workThread, FALSE); + CloseThreadpoolWork(m_workThread); + + //load next file + m_curFile++; + if (m_curFile == numFiles) m_curFile = 0; + m_fileLoaded = LoadFile(g_FileList[m_curFile]); + + //if successfully loaded, start up thread and playing new file + if (m_fileLoaded) + { + m_bThreadActive = true; + m_bPlayingSound = true; + m_workThread = CreateThreadpoolWork(SpatialWorkCallback, this, nullptr); + SubmitThreadpoolWork(m_workThread); + } + } + else + { + //if thread active but paused, shutdown thread to load new file + if (m_bThreadActive) + { + m_bThreadActive = false; + m_bPlayingSound = false; + WaitForThreadpoolWorkCallbacks(m_workThread, FALSE); + CloseThreadpoolWork(m_workThread); + } + + //load next file + m_curFile++; + if (m_curFile == numFiles) m_curFile = 0; + m_fileLoaded = LoadFile(g_FileList[m_curFile]); + } + } + } + + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + auto rect = m_deviceResources->GetOutputSize(); + auto safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + + wchar_t str[256] = { 0 }; + swprintf_s(str, L"Simple Spatial Playback:"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + if (!m_Renderer->IsActive()) + { + swprintf_s(str, L"Spatial Renderer Not Available"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 60; + } + else + { + swprintf_s(str, L" File: %s", g_FileList[m_curFile]); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L" State: %s", ((m_bPlayingSound) ? L"Playing" : L"Stopped")); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L"Use 'A' Button to start/stop playback"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + swprintf_s(str, L"Use 'B' Button to change to next file"); + m_font->DrawString(m_spriteBatch.get(), str, pos, ATG::Colors::White); + pos.y += 30; + } + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_spriteBatch = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion + +HRESULT Sample::InitializeSpatialStream(void) +{ + HRESULT hr = S_OK; + + if (!m_Renderer) + { + // Create a new ISAC instance + m_Renderer = Microsoft::WRL::Make(); + // Selects the Default Audio Device + hr = m_Renderer->InitializeAudioDeviceAsync(); + } + + return hr; +} + +bool Sample::LoadFile(LPCWSTR inFile) +{ + //clear and reset wavchannels + for (UINT32 i = 0; i < MAX_CHANNELS; i++) + { + if (WavChannels[i].buffersize) + { + delete[] WavChannels[i].wavBuffer; + } + WavChannels[i].buffersize = 0; + WavChannels[i].curBufferLoc = 0; + WavChannels[i].object = nullptr; + } + + HRESULT hr = S_OK; + std::unique_ptr m_waveFile; + DX::WAVData WavData; + hr = DX::LoadWAVAudioFromFileEx(inFile, m_waveFile, WavData); + if (FAILED(hr)) + { + return false; + } + + if ((WavData.wfx->wFormatTag == 1 || WavData.wfx->wFormatTag == 65534) && WavData.wfx->nSamplesPerSec == 48000) + { + numChannels = WavData.wfx->nChannels; + + int numSamples = WavData.audioBytes / (2 * numChannels); + for (int i = 0; i < numChannels; i++) + { + WavChannels[i].wavBuffer = new char[numSamples * 4]; + WavChannels[i].buffersize = numSamples * 4; + } + + float * tempnew; + short * tempdata = (short *)WavData.startAudio; + + for (int i = 0; i < numSamples; i++) + { + for (int j = 0; j < numChannels; j++) + { + int chan = j; + tempnew = (float *)WavChannels[chan].wavBuffer; + int sample = (i * numChannels) + chan; + tempnew[i] = (float)tempdata[sample] / 32768; + } + } + } + else if ((WavData.wfx->wFormatTag == 3) && WavData.wfx->nSamplesPerSec == 48000) + { + numChannels = WavData.wfx->nChannels; + int numSamples = WavData.audioBytes / (4 * numChannels); + for (int i = 0; i < numChannels; i++) + { + WavChannels[i].wavBuffer = new char[numSamples * 4]; + WavChannels[i].buffersize = numSamples * 4; + } + + float * tempnew; + float * tempdata = (float *)WavData.startAudio; + + for (int i = 0; i < numSamples; i++) + { + for (int j = 0; j < numChannels; j++) + { + int chan = j; + tempnew = (float *)WavChannels[chan].wavBuffer; + int sample = (i * numChannels) + chan; + tempnew[i] = (float)tempdata[sample]; + } + } + } + else + { + return false; + } + + return true; +} + + + +void Sample::SetChannelPosVolumes(void) +{ + WavChannels[0].volume = 1.f; + WavChannels[0].objType = AudioObjectType_FrontLeft; + + WavChannels[1].volume = 1.f; + WavChannels[1].objType = AudioObjectType_FrontRight; + + WavChannels[2].volume = 1.f; + WavChannels[2].objType = AudioObjectType_FrontCenter; + + WavChannels[3].volume = 1.f; + WavChannels[3].objType = AudioObjectType_LowFrequency; + + WavChannels[4].volume = 1.f; + WavChannels[4].objType = AudioObjectType_BackLeft; + + WavChannels[5].volume = 1.f; + WavChannels[5].objType = AudioObjectType_BackRight; + + WavChannels[6].volume = 1.f; + WavChannels[6].objType = AudioObjectType_SideLeft; + + WavChannels[7].volume = 1.f; + WavChannels[7].objType = AudioObjectType_SideRight; + + WavChannels[8].volume = 1.f; + WavChannels[8].objType = AudioObjectType_TopFrontLeft; + + WavChannels[9].volume = 1.f; + WavChannels[9].objType = AudioObjectType_TopFrontRight; + + WavChannels[10].volume = 1.f; + WavChannels[10].objType = AudioObjectType_TopBackLeft; + + WavChannels[11].volume = 1.f; + WavChannels[11].objType = AudioObjectType_TopBackRight; + +} + diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.h b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.h new file mode 100644 index 0000000000000000000000000000000000000000..467994c4fcfe8f242d28714c0420a5665d120b31 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.h @@ -0,0 +1,96 @@ +//-------------------------------------------------------------------------------------- +// SimpleSpatialPlaySoundXDK.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "SpriteFont.h" +#include "ISACRenderer.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +#define MAX_CHANNELS 12 //up to 7.1.4 channels + + struct Audiochannel + { + char * wavBuffer; + UINT32 buffersize; + float volume; + UINT32 curBufferLoc; + + Microsoft::WRL::ComPtr object; + AudioObjectType objType; + + }; + +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // Messages + void OnSuspending(); + void OnResuming(); + + + Microsoft::WRL::ComPtr m_Renderer; + + int numChannels; + Audiochannel WavChannels[MAX_CHANNELS]; + bool m_bThreadActive; + bool m_bPlayingSound; + int availableObjects; + + +private: + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + bool LoadFile(LPCWSTR inFile); + + void SetChannelPosVolumes(void); + HRESULT InitializeSpatialStream(void); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + bool m_fileLoaded; + int m_curFile; + + //worker thread for spatial system + PTP_WORK m_workThread; + +}; diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.sln b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.sln new file mode 100644 index 0000000000000000000000000000000000000000..e4bc2b718e4580be7cb0e82e9dd6fd9bd02d8720 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleSpatialPlaySoundXDK", "SimpleSpatialPlaySoundXDK.vcxproj", "{8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Debug|Durango.ActiveCfg = Debug|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Debug|Durango.Build.0 = Debug|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Debug|Durango.Deploy.0 = Debug|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Profile|Durango.ActiveCfg = Profile|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Profile|Durango.Build.0 = Profile|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Profile|Durango.Deploy.0 = Profile|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Release|Durango.ActiveCfg = Release|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Release|Durango.Build.0 = Release|Durango + {8D1B958E-AAB0-48CF-BD60-C39A7FEBB662}.Release|Durango.Deploy.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.vcxproj b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..ed16519cecc9d3e4bf59d1e8f7d933bc13df0bb8 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.vcxproj @@ -0,0 +1,215 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleSpatialPlaySoundXDK + {8d1b958e-aab0-48cf-bd60-c39a7febb662} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + mmdevapi.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + + + + + mmdevapi.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + + + + + MFplat.lib;mmdevapi.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.vcxproj.filters b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..69727c12ffafd4ff157ae6dc01a7c6c2211066f4 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/SimpleSpatialPlaySoundXDK.vcxproj.filters @@ -0,0 +1,81 @@ + + + + + 58c2a4ad-94cc-46b7-a31b-ca3e072f18b9 + + + 47d8bfa9-7bbd-490c-b646-0d31e8a9317f + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {e4d804ca-14eb-4f67-8112-df83634be576} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + + + Assets + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/StepTimer.h b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Telemetry.h b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/pch.cpp b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/pch.h b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..a832c3a7c964a63a8f2a0747e9658d13a92fe926 --- /dev/null +++ b/XDKSamples/Audio/SimpleSpatialPlaySoundXDK/pch.h @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR/Assets/Logo.png b/XDKSamples/Graphics/SimpleHDR/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR/Assets/Logo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR/Assets/SmallLogo.png b/XDKSamples/Graphics/SimpleHDR/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR/Assets/SmallLogo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR/Assets/SplashScreen.png b/XDKSamples/Graphics/SimpleHDR/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR/Assets/SplashScreen.png differ diff --git a/XDKSamples/Graphics/SimpleHDR/Assets/StoreLogo.png b/XDKSamples/Graphics/SimpleHDR/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR/Assets/StoreLogo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR/Assets/WideLogo.png b/XDKSamples/Graphics/SimpleHDR/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR/Assets/WideLogo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR/ColorPS.hlsl b/XDKSamples/Graphics/SimpleHDR/ColorPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..47953d4e6a4029862a0e146d5db4c78f4d288f2b --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/ColorPS.hlsl @@ -0,0 +1,13 @@ +//-------------------------------------------------------------------------------------- +// ColorPS.hlsl +// +// A custom pixel shader for SpriteBatch that only outputs color +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +float4 main(float4 color : COLOR) : SV_Target0 +{ + return color; +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR/DeviceResources.cpp b/XDKSamples/Graphics/SimpleHDR/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e09ab267165615437c549781f3fb0b91a79cd21 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/DeviceResources.cpp @@ -0,0 +1,339 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// +// NOTE: This is a customized version of DeviceResources.cpp that has specific implementation for HDR swapchain creation +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT gameDVRFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat(gameDVRFormat) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dHDR10RenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dHDR10RenderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChainHDR10) + { + // HDR: If the HDR10 swap chain already exists, resize it. + ThrowIfFailed(m_swapChainHDR10->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + DXGI_FORMAT_R10G10B10A2_UNORM, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // HDR: Create HDR10 swapchain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // HDR: HDR10 swapchain must be 10:10:10:2. + swapChainDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + + // HDR: The HDR swapchain buffer needs to use the ST.2084 curve with Rec.2020 color primaries. + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084; + + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainHDR10.GetAddressOf() + )); + } + + if (m_swapChainGameDVR) + { + // HDR: If the GameDVR SDR swap chain already exists, resize it. + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + else + { + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // HDR: Create GameDVR SDR swapchain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // HDR: GameDVR SDR swapchain can be 8:8:8:8, 8:8:8:8_SRGB, or 10:10:10:2. + swapChainDesc.Format = m_gameDVRFormat; + + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + + // HDR: Create a render target view of the HDR10 swap chain back buffer. + ThrowIfFailed(m_swapChainHDR10->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dHDR10RenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dHDR10RenderTarget->SetName(L"HDR10 Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dHDR10RenderTarget.Get(), + nullptr, + m_d3dHDR10RenderTargetView.ReleaseAndGetAddressOf() + )); + + // HDR: Create a render target view of the GameDVR SDR swap chain back buffer. + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChainHDR10->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dHDR10RenderTarget.ReleaseAndGetAddressOf()))); + m_d3dDevice->PlaceSwapChainView(m_d3dHDR10RenderTarget.Get(), m_d3dHDR10RenderTargetView.Get()); + m_d3dContext->InsertWaitOnPresent(0, m_d3dHDR10RenderTarget.Get()); + + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(bool hdrEnabled, UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_d3dHDR10RenderTarget.Get(), 0, nullptr, + m_d3dHDR10RenderTarget.Get(), 0, nullptr, + DXGI_FORMAT_R10G10B10A2_UNORM, decompressFlags); + + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + + // HDR - Present the HDR and SDR swapchains + if (hdrEnabled) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChainHDR10.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1] = presentParameterSets[0]; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChainGameDVR->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/Graphics/SimpleHDR/DeviceResources.h b/XDKSamples/Graphics/SimpleHDR/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..5f0356b94bcb875208cad79313f61bb09f993944 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/DeviceResources.h @@ -0,0 +1,88 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// +// NOTE: This is a customized version of DeviceResources.cpp that has specific implementation for HDR swapchain creation +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT gameDVRFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(bool hdrEnabled = false, UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR10 swapchain. + IDXGISwapChain1* GetHDR10SwapChain() const { return m_swapChainHDR10.Get(); } + ID3D11Texture2D* GetHDR10RenderTarget() const { return m_d3dHDR10RenderTarget.Get(); } + ID3D11RenderTargetView* GetHDR10RenderTargetView() const { return m_d3dHDR10RenderTargetView.Get(); } + DXGI_FORMAT GetHDR10Format() const { return DXGI_FORMAT_R10G10B10A2_UNORM; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR10 swapchain. + Microsoft::WRL::ComPtr m_swapChainHDR10; + Microsoft::WRL::ComPtr m_d3dHDR10RenderTarget; + Microsoft::WRL::ComPtr m_d3dHDR10RenderTargetView; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR/Main.cpp b/XDKSamples/Graphics/SimpleHDR/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fe4cfe135c79a45d5c1fe61370373af2e56a609 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleHDR.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/Graphics/SimpleHDR/Package.appxmanifest b/XDKSamples/Graphics/SimpleHDR/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..af25f96285cffa8d6b186ddec68e65d7aed34791 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleHDR (DirectX 11) + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleHDR for DirectX 11 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Graphics/SimpleHDR/PrepareSwapChainBuffersPS.hlsl b/XDKSamples/Graphics/SimpleHDR/PrepareSwapChainBuffersPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..094cb38655170574227a8ddc3f988dcec367ae2b --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/PrepareSwapChainBuffersPS.hlsl @@ -0,0 +1,54 @@ +//-------------------------------------------------------------------------------------- +// PrepareSwapChainBuffersPS.hlsl +// +// Takes the final HDR back buffer with linear values using Rec.709 color primaries and +// outputs two signals, an HDR and SDR signal. The HDR siganl uses Rec.2020 color primaries +// with the ST.2084 curve, whereas the SDR signal uses Rec.709 color primaries which the +// hardware will apply the Rec.709 gamma curve. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "HDRCommon.hlsli" + +SamplerState PointSampler : register(s0); // Point sample the HDR scene +Texture2D HDRScene : register(t0); // HDR scene with linear values using Rec.709 primaries +float4 PaperWhiteNits : register(b0); // Defines how bright white is (in nits), which controls how bright the SDR range in the image will be, e.g. 200 nits + + +// Very simple HDR to SDR tonemapping, which simply clips values above 1.0f from the HDR scene. +float4 TonemapHDR2SDR(float4 hdrSceneValue) +{ + return saturate(hdrSceneValue); +} + +struct Interpolants +{ + float4 color : COLOR; + float2 texCoord : TEXCOORD; +}; + +struct PSOut +{ + float4 HDR10 : SV_Target0; // HDR10 buffer using Rec.2020 color primaries with ST.2084 curve + float4 GameDVR : SV_Target1; // GameDVR buffer using Rec.709 color primaries with sRGB gamma curve +}; + + +// Prepare the HDR swapchain buffer as HDR10. This means the buffer has to contain data which uses +// - Rec.2020 color primaries +// - Quantized using ST.2084 curve +// - 10-bit per channel +PSOut main(Interpolants In) +{ + PSOut output; + + // Input is linear values using sRGB / Rec.709 color primaries + float4 hdrSceneValues = HDRScene.Sample(PointSampler, In.texCoord); + + output.HDR10 = ConvertToHDR10(hdrSceneValues, PaperWhiteNits.x); + output.GameDVR = TonemapHDR2SDR(hdrSceneValues); + + return output; +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR/Readme.docx b/XDKSamples/Graphics/SimpleHDR/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..2d7a7172f34fddc6fc153c5a64af6d0db6b6ed7f Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR/Readme.docx differ diff --git a/XDKSamples/Graphics/SimpleHDR/SimpleHDR.cpp b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d8cb8d8203f467ec162fb6d370ff8697aeeddc4 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.cpp @@ -0,0 +1,850 @@ +//-------------------------------------------------------------------------------------- +// SimpleHDR.cpp +// +// This sample uses an API to determine if the attached display is HDR capable. If so, it +// will switch the display to HDR mode. A very simple HDR scene, with values above 1.0f, +// is rendered to a FP16 backbuffer and outputs to two different swapchains, one for HDR +// and one for SDR. Even if the consumer uses an HDR display, the SDR signal is still +// required for GameDVR and screenshots. +// +// Requirements for swapchain creation: +// 1) HDR swapchain has to be 10bit using DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 +// 2) SDR swapchain has to use DXGI_FORMAT_B8G8R8A8_UNORM_SRGB +// See DeviceResources.cpp for swapchain creation and presentation +// +// Refer to the white paper “HDR on Xbox One” +// +// Up to now, games were outputting and SDR signal using Rec.709 color primaries and Rec.709 +// gamma curve. One new feature of UHD displays is a wider color gamut (WCG). To use this +// we need to use a new color space, Rec.2020 color primaries. Another new feature of UHD +// displays is high dynamic range (HDR). To use this we need to use a different curve, the +// ST.2084 curve. Therefore, to output an HDR signal, it needs to use Rec.2020 color primaries +// with ST.2084 curve. +// +// For displaying the SDR signal, a simple tonemapping shader is applied to simply clip all +// values above 1.0f in the HDR scene, and outputs 8bit values using Rec.709 color primaries, +// with the gamma curve applied. +// +// For displaying the HDR signal, a shader is used to rotate the Rec.709 color primaries to +// Rec.2020 color primaries, and then apply the ST.2084 curve to output 10bit values which +// the HDR display can correctly display. The whiteness and brightness of the output on an +// HDR display will be determined by the selected nits value for defining “paper white”. +// SDR specs define “paper white” as 80nits, but this is for a cinema with a dark environment. +// Consumers today are used to much brighter whites, e.g. ~550 nits for a smartphone(so that it +// can be viewed in sunlight), 200-300 nits for a PC monitor, 120-150 nits for an SDR TV, etc. +// The nits for “paper white” can be adjusted in the sample using the DPad up/down. Displaying +// bright values next to white can be deceiving to the eye, so you can use the A button to +// toggle if you only want to see the “paper white” block. +// +// The sample has two modes: +// 1) Render blocks with specific values in the scene +// 2) Render ST.2084 curve with specific brightness values(nits) +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleHDR.h" +#include "HDRCommon.h" +#include +#include "ReadData.h" +#include "ControllerFont.h" +#include + +using namespace DX; +using namespace DirectX; +using namespace SimpleMath; +using namespace Colors; +using Microsoft::WRL::ComPtr; + + +#pragma region HDR + +// Initialize, including trying to set the display to HDR mode +void Sample::Initialize(IUnknown* window) +{ + m_bIsTVInHDRMode = false; + + // Determine if attached display is HDR or SDR, if HDR, also set the TV in HDR mode. This is an async operation, + // so we can do other initalizations in the meanwhile + auto determineHDRAction = Windows::Xbox::Graphics::Display::DisplayConfiguration::TrySetHdrModeAsync(); + auto determineHDRTask = Concurrency::create_task(determineHDRAction); + + // Regular sample initialization + Init(window); + + // Now wait until we know if display is in HDR mode + try + { + // .get() will automatically .wait() until the async operation is done + auto results = determineHDRTask.get(); + m_bIsTVInHDRMode = results->HdrEnabled; + } + catch (Platform::Exception^ e) + { + OutputDebugStringW(e->Message->Data()); + throw; + } +} + + +// Render +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"Render"); + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + if (m_bRender2084Curve) + { + // Render the ST.2084 curve + Render2084Curve(); + } + else + { + // Render the HDR scene with values larger than 1.0f, which will be perceived as bright + RenderHDRScene(); + } + + // Render the UI with values of 1.0f, which will be perceived as white + RenderUI(); + + // Process the HDR scene so that the swapchains can correctly be sent to HDR or SDR display + PrepareSwapChainBuffers(); + + PIXEndEvent(d3dContext); + + // Show the new frame. + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(m_bIsTVInHDRMode); + m_graphicsMemory->Commit(); + PIXEndEvent(d3dContext); +} + + +// Process the HDR scene so that the swapchains can correctly be sent to HDR or SDR display +void Sample::PrepareSwapChainBuffers() +{ + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + auto pHDRSceneSRV = m_d3dHDRSceneSRV.Get(); // Samples the HDR scene values + auto pHDR10RTV = m_deviceResources->GetHDR10RenderTargetView(); // Writes out the HDR scene values with ST.2084 into HDR swapchain + auto pGameDVRRTV = m_deviceResources->GetGameDVRRenderTargetView(); // Writes out the HDR tonemapped values into SDR swapchain, then display HW applies gamma curve + auto viewport = m_deviceResources->GetScreenViewport(); + auto pPointSampler = m_d3dPointSampler.Get(); + auto pNitsForPaperWhiteCB = m_d3dNitsForPaperWhiteCB.Get(); + + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"PrepareSwapChainBuffers"); + + ID3D11RenderTargetView* pRTVs[] = { pHDR10RTV, pGameDVRRTV }; + d3dContext->OMSetRenderTargets(2, pRTVs, nullptr); + + d3dContext->RSSetViewports(1, &viewport); + + // Render a fullscreen quad and apply the HDR/SDR shaders + m_fullScreenQuad->Draw(d3dContext, *m_states, pHDRSceneSRV, [=] + { + d3dContext->PSSetShader(m_d3dPrepareSwapChainBuffersPS.Get(), nullptr, 0); + d3dContext->PSSetConstantBuffers(0, 1, &pNitsForPaperWhiteCB); + d3dContext->PSSetSamplers(0, 1, &pPointSampler); + + }); + + PIXEndEvent(d3dContext); +} + + +// Clamp value between 0 and 1 +inline float Clamp(float value) +{ + return std::min(std::max(value, 0.0f), 1.0f); +} + +// Applies the sRGB gamma curve to a linear value. This function is only used to output UI values +float LinearToSRGB(float hdrSceneValue) +{ + const float Cutoff = 0.0031308f; + const float Linear = 12.92f; + const float Scale = 1.055f; + const float Bias = 0.055f; + const float Gamma = 2.4f; + const float InvGamma = 1.0f / Gamma; + + // clamp values [0..1] + hdrSceneValue = Clamp(hdrSceneValue); + + // linear piece for dark values + if (hdrSceneValue < Cutoff) + { + return hdrSceneValue * Linear; + } + + return Scale * std::pow(hdrSceneValue, InvGamma) - Bias; +} + + +// Render the HDR scene with four squares, each with a different HDR value. Values larger than 1.0f will be perceived as bright +void Sample::RenderHDRScene() +{ + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + + auto viewportUI = m_deviceResources->GetScreenViewport(); + viewportUI.Width = 1920; + viewportUI.Height = 1080; + m_spriteBatch->SetViewport(viewportUI); + + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"RenderHDRScene"); + + const long step = static_cast(1920.0f / (NUM_INPUT_VALUES + 2.0f)); + + float startX = 115; + + RECT position = { 0 }; + position.left = static_cast(startX); + + // Render each block with the specific HDR scene value + for (int i = 0; i < NUM_INPUT_VALUES; i++) + { + XMVECTOR hdrSceneColor = MakeColor(m_hdrSceneValues[i]); + + m_spriteBatch->Begin(SpriteSortMode_Immediate, nullptr, nullptr, nullptr, nullptr, [=] + { + d3dContext->PSSetShader(m_d3dColorPS.Get(), nullptr, 0); + }); + + position.left += step; + position.top = 485; + position.right = position.left + static_cast(step / 1.25f); + position.bottom = position.top + 250; + + // The shader will only output color values, but the Draw() function needs a texture pointer, i.e. m_d3dHDRSceneSRV isn't used when drawing the sqaures + if (!m_bShowOnlyPaperWhite) + { + m_spriteBatch->Draw(m_d3dHDRSceneSRV.Get(), position, hdrSceneColor); + } + else if (XMVector2Equal(hdrSceneColor, White)) + { + m_spriteBatch->Draw(m_d3dHDRSceneSRV.Get(), position, hdrSceneColor); + } + + m_spriteBatch->End(); + } + + // Render the text + wchar_t strText[2048] = {}; + const float startY = 40.0f; + const float fontScale = 0.75f; + + Vector2 fontPos; + + startX = 50.0f; + + m_spriteBatch->Begin(); + + fontPos.x = startX; + fontPos.y = startY + 270.0f; + m_font->DrawString(m_spriteBatch.get(), L"HDR Scene Values", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + m_font->DrawString(m_spriteBatch.get(), L"SDR sRGB Curve", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + m_font->DrawString(m_spriteBatch.get(), L"HDR ST.2084 Curve", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + m_font->DrawString(m_spriteBatch.get(), L"HDR Nits Output", fontPos, White, 0.0f, g_XMZero, fontScale); + + fontPos.x = startX + 100.0f; + + for (int i = 0; i < NUM_INPUT_VALUES; i++) + { + float hdrSceneValue = m_hdrSceneValues[i]; + float sdrGamma = LinearToSRGB(hdrSceneValue); + float hdr2084 = LinearToST2084(hdrSceneValue, m_currentPaperWhiteNits); + float hdrNits = CalcNits(hdrSceneValue, m_currentPaperWhiteNits); + + fontPos.x += step; + fontPos.y = startY + 270.0f; + swprintf_s(strText, L"%f", hdrSceneValue); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + swprintf_s(strText, L"%f", sdrGamma); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + swprintf_s(strText, L"%f", hdr2084); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + swprintf_s(strText, L"%f", hdrNits); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + } + + fontPos.y = startY + 700.0f; + fontPos.x = startX + 100.0f + step + step - 15.0f; + m_font->DrawString(m_spriteBatch.get(), L"Paper White", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.x += step + 45; + + if (!m_bShowOnlyPaperWhite) + { + m_font->DrawString(m_spriteBatch.get(), L"Bright", fontPos, White, 0.0f, g_XMZero, fontScale); + } + + m_spriteBatch->End(); + + PIXEndEvent(d3dContext); +} + + +// Render the ST.2084 curve +void Sample::Render2084Curve() +{ + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"Render2084Curve"); + + auto outputSize = m_deviceResources->GetOutputSize(); + float scale = (outputSize.bottom - outputSize.top) / 1080.0f; + + float viewportWidth = 1675 * scale; + float viewportHeight = 600 * scale; + float startX = 150.0f; + float startY = 250.0f; + + auto viewport = m_deviceResources->GetScreenViewport(); + viewport.TopLeftX = startX * scale; + viewport.TopLeftY = startY * scale; + viewport.Width = viewportWidth; + viewport.Height = viewportHeight; + d3dContext->RSSetViewports(1, &viewport); + + Matrix proj = Matrix::CreateOrthographicOffCenter(0.0f, viewportWidth, viewportHeight, 0.0f, 0.0f, 1.0f); + + m_lineEffect->SetProjection(proj); + d3dContext->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF); + d3dContext->OMSetDepthStencilState(m_states->DepthNone(), 0); + d3dContext->RSSetState(m_states->CullNone()); + m_lineEffect->Apply(d3dContext); + d3dContext->IASetInputLayout(m_inputLayout.Get()); + m_primitiveBatch->Begin(); + + // Render the outline + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(0.5f, 0.5f, 0), White), VertexPositionColor(Vector3(viewportWidth, 0.5f, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(0.5f, viewportHeight, 0), White), VertexPositionColor(Vector3(viewportWidth, viewportHeight, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(0.5f, 0.5f, 0), White), VertexPositionColor(Vector3(0.5f, viewportHeight, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(viewportWidth, 0.5f, 0), White), VertexPositionColor(Vector3(viewportWidth, viewportHeight, 0), White)); + + // Render horizontal tick marks + float numSteps = 16; + for (int i = 0; i < numSteps; i++) + { + float x = (i * (viewportWidth / numSteps)) + 0.5f; + float y = viewportHeight; + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, y, 0), White), VertexPositionColor(Vector3(x, y - 10, 0), White)); + } + + // Render the graph + for (int i = 0; i < viewportWidth; i++) + { + float x1 = static_cast(i) + 0.5f; + float normalizedLinearValue = static_cast(i) / viewportWidth; + float normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + float y1 = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + float x2 = x1 + 1; + normalizedLinearValue = static_cast(x2) / viewportWidth; + normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + float y2 = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x1, y1, 0), White), VertexPositionColor(Vector3(x2, y2, 0), White)); + } + + // Render the lines indication the current selection + float normalizedLinearValue = m_current2084CurveRenderingNits / g_MaxNitsFor2084; + float normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + float x = normalizedLinearValue * viewportWidth; + float y = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, viewportHeight, 0), White), VertexPositionColor(Vector3(x, y, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, y, 0), White), VertexPositionColor(Vector3(0, y, 0), White)); + + m_primitiveBatch->End(); + + // Restore viewport + viewport = m_deviceResources->GetScreenViewport(); + d3dContext->RSSetViewports(1, &viewport); + + auto viewportUI = m_deviceResources->GetScreenViewport(); + viewportUI.Width = 1920; + viewportUI.Height = 1080; + m_spriteBatch->SetViewport(viewportUI); + + // Render text + viewportWidth /= scale; + viewportHeight /= scale; + + wchar_t strText[2048] = {}; + Vector2 fontPos; + m_spriteBatch->Begin(); + + fontPos.x = startX - 100; + fontPos.y = startY + viewportHeight + 5; + m_font->DrawString(m_spriteBatch.get(), L"Linear", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + m_font->DrawString(m_spriteBatch.get(), L"Nits", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + m_font->DrawString(m_spriteBatch.get(), L"HDR Scene", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + + fontPos.x = startX + viewportWidth - 5; + fontPos.y = startY + viewportHeight + 5; + m_font->DrawString(m_spriteBatch.get(), L"1.0", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; // Always [0..1] + m_font->DrawString(m_spriteBatch.get(), L"10K", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; // Spec defines 10K nits + + // Max HDR scene value changes as white paper nits change + float hdrSceneValue = CalcHDRSceneValue(g_MaxNitsFor2084, m_currentPaperWhiteNits); + swprintf_s(strText, L"%1.0f", hdrSceneValue); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + + normalizedLinearValue = m_current2084CurveRenderingNits / g_MaxNitsFor2084; + normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + hdrSceneValue = CalcHDRSceneValue(m_current2084CurveRenderingNits, m_currentPaperWhiteNits); + + x = normalizedLinearValue * viewportWidth + 1; + y = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + fontPos.x = startX + x; + fontPos.y = startY + viewportHeight + 5; + swprintf_s(strText, L"%1.2f", normalizedLinearValue); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + swprintf_s(strText, L"%1.0f", m_current2084CurveRenderingNits); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + swprintf_s(strText, L"%1.2f", hdrSceneValue); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + + fontPos.x = startX - 25; + fontPos.y = startY - 50; + m_font->DrawString(m_spriteBatch.get(), L"ST.2084", fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); fontPos.x -= 20; + m_font->DrawString(m_spriteBatch.get(), L"Nits", fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); + + fontPos.x = startX - 25; + fontPos.y = y + startY; + swprintf_s(strText, L"%1.2f", normalizedNonLinearValue); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); fontPos.x -= 20; + swprintf_s(strText, L"%1.0f", m_current2084CurveRenderingNits); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); + + m_spriteBatch->End(); + + // Render blocks + const long size = 150; + RECT position = { 0 }; + position.left = 1920 - size * 4; + position.top = 50; + position.right = position.left + size; + position.bottom = position.top + size; + + m_spriteBatch->Begin(SpriteSortMode_Immediate, nullptr, nullptr, nullptr, nullptr, [=] + { + d3dContext->PSSetShader(m_d3dColorPS.Get(), nullptr, 0); + }); + + m_spriteBatch->Draw(m_d3dHDRSceneSRV.Get(), position, White); + + position.left += size * 2; + position.right = position.left + size; + + XMVECTORF32 color = { hdrSceneValue, hdrSceneValue, hdrSceneValue, 1.0f }; + m_spriteBatch->Draw(m_d3dHDRSceneSRV.Get(), position, color); + + m_spriteBatch->End(); + + // Render text for blocks + m_spriteBatch->Begin(); + + fontPos.x = 1920 - size * 4 - 25; + fontPos.y = static_cast(position.bottom - 15); + + m_font->DrawString(m_spriteBatch.get(), L"Paper White", fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); + + fontPos.x = 1920 - size * 4 + 25; + fontPos.y = static_cast(position.bottom); + + swprintf_s(strText, L"%1.0f nits", m_currentPaperWhiteNits); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.x += size * 2; + swprintf_s(strText, L"%1.0f nits", m_current2084CurveRenderingNits); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); + + m_spriteBatch->End(); + + PIXEndEvent(d3dContext); +} + + +// Render the UI +void Sample::RenderUI() +{ + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"RenderUI"); + + auto viewportUI = m_deviceResources->GetScreenViewport(); + viewportUI.Width = 1920; + viewportUI.Height = 1080; + m_spriteBatch->SetViewport(viewportUI); + + const float startX = 50.0f; + const float startY = 40.0f; + const float fontScale = 0.75f; + + Vector2 fontPos(startX, startY); + + m_spriteBatch->Begin(); + m_font->DrawString(m_spriteBatch.get(), L"SimpleHDR Sample for DirectX 11", fontPos, White, 0.0f, g_XMZero, 1.0f); + + if (!m_bRender2084Curve) + { + fontPos.y = startY + 100.0f; + if (m_bIsTVInHDRMode) + { + m_font->DrawString(m_spriteBatch.get(), L"TV in HDR Mode: TRUE", fontPos, White, 0.0f, g_XMZero, fontScale); + } + else + { + m_font->DrawString(m_spriteBatch.get(), L"TV in HDR Mode: FALSE", fontPos, White, 0.0f, g_XMZero, fontScale); + } + } + + fontPos.x = startX; + fontPos.y = 955; + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_controllerFont.get(), L"[A] - Toggle displaying ST.2084 curve", fontPos, White, 0.65f); fontPos.y += 35; + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_controllerFont.get(), L"[B] - Toggle displaying only paper white block", fontPos, White, 0.65f); fontPos.y += 35; + + fontPos.x = (1920.0f/2.0f) + startX; + fontPos.y = 955; + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_controllerFont.get(), L"[DPad] - Adjust paper white nits", fontPos, White, 0.65f); fontPos.y += 35; + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_controllerFont.get(), L"[LThumb] - Adjust values quickly", fontPos, White, 0.65f); fontPos.y += 35; + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_controllerFont.get(), L"[RThumb] - Adjust values slowly", fontPos, White, 0.65f); fontPos.y += 35; + + if (m_countDownToBright >= 0) + { + fontPos.x = 1170; + fontPos.y = 550; + + wchar_t strText[2048] = {}; + swprintf_s(strText, L"%1.0f", m_countDownToBright); + m_font->DrawString(m_spriteBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 1.75f); + } + + m_spriteBatch->End(); + + PIXEndEvent(d3dContext); +} + + +// Clear scene +void Sample::Clear() +{ + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + auto pHDRSceneRTV = m_d3dHDRSceneRTV.Get(); + auto pDSV = m_deviceResources->GetDepthStencilView(); + auto viewport = m_deviceResources->GetScreenViewport(); + + PIXBeginEvent(d3dContext, PIX_COLOR_DEFAULT, L"Clear"); + + d3dContext->ClearRenderTargetView(pHDRSceneRTV, Colors::Black); + d3dContext->ClearDepthStencilView(pDSV, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + d3dContext->OMSetRenderTargets(1, &pHDRSceneRTV, pDSV); + d3dContext->RSSetViewports(1, &viewport); + + PIXEndEvent(d3dContext); +} + +#pragma endregion + +#pragma region Frame Update + +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + static bool bCountingDownToBright = true; + m_countDownToBright -= timer.GetElapsedSeconds(); + if (bCountingDownToBright && (m_countDownToBright < 0)) + { + bCountingDownToBright = false; + m_bShowOnlyPaperWhite = false; + } + + auto gamepad = m_gamePad->GetState(0); + + if (gamepad.IsConnected()) + { + if (gamepad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + m_gamePadButtons.Update(gamepad); + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_bRender2084Curve = !m_bRender2084Curve; + } + + if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + m_bShowOnlyPaperWhite = !m_bShowOnlyPaperWhite; + } + + if (m_gamePadButtons.dpadDown == GamePad::ButtonStateTracker::PRESSED || + m_gamePadButtons.dpadLeft == GamePad::ButtonStateTracker::PRESSED) + { + m_currentPaperWhiteNits -= 20.0f;; + m_currentPaperWhiteNits = std::max(m_currentPaperWhiteNits, 80.0f); + + // Update constant buffer + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + auto d3dBuffer = m_d3dNitsForPaperWhiteCB.Get(); + D3D11_MAPPED_SUBRESOURCE mappedResource; + DX::ThrowIfFailed(d3dContext->Map(d3dBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)); + XMFLOAT4* pData = (XMFLOAT4*)mappedResource.pData; + *pData = { m_currentPaperWhiteNits, 0.0f, 0.0f, 0.0f }; + d3dContext->Unmap(d3dBuffer, 0); + } + + if (m_gamePadButtons.dpadUp == GamePad::ButtonStateTracker::PRESSED || + m_gamePadButtons.dpadRight == GamePad::ButtonStateTracker::PRESSED) + { + m_currentPaperWhiteNits += 20.0f; + m_currentPaperWhiteNits = std::min(m_currentPaperWhiteNits, g_MaxNitsFor2084); + + // Update constant buffer + auto d3dContext = m_deviceResources->GetD3DDeviceContext(); + auto d3dBuffer = m_d3dNitsForPaperWhiteCB.Get(); + D3D11_MAPPED_SUBRESOURCE mappedResource; + DX::ThrowIfFailed(d3dContext->Map(d3dBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)); + XMFLOAT4* pData = (XMFLOAT4*)mappedResource.pData; + *pData = { m_currentPaperWhiteNits, 0.0f, 0.0f, 0.0f }; + d3dContext->Unmap(d3dBuffer, 0); + } + + const float fastNitsDelta = 25.0f; + const float slowNitsDelta = 1.0f; + const float fastSceneValueDelta = 0.05f; + const float slowSceneValueDelta = 0.005f; + + if (gamepad.IsLeftThumbStickDown() || gamepad.IsLeftThumbStickLeft()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits -= fastNitsDelta; + m_current2084CurveRenderingNits = std::max(m_current2084CurveRenderingNits, 0.0f); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] -= fastSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::max(m_hdrSceneValues[g_CustomInputValueIndex], 0.0f); + } + } + + if ( gamepad.IsRightThumbStickDown() || gamepad.IsRightThumbStickLeft()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits -= slowNitsDelta; + m_current2084CurveRenderingNits = std::max(m_current2084CurveRenderingNits, 0.0f); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] -= slowSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::max(m_hdrSceneValues[g_CustomInputValueIndex], 0.0f); + } + } + + if (gamepad.IsLeftThumbStickUp() || gamepad.IsLeftThumbStickRight()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits += fastNitsDelta; + m_current2084CurveRenderingNits = std::min(m_current2084CurveRenderingNits, g_MaxNitsFor2084); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] += fastSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::min(m_hdrSceneValues[g_CustomInputValueIndex], 125.0f); + } + } + + if (gamepad.IsRightThumbStickUp() || gamepad.IsRightThumbStickRight()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits += slowNitsDelta; + m_current2084CurveRenderingNits = std::min(m_current2084CurveRenderingNits, g_MaxNitsFor2084); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] += slowSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::min(m_hdrSceneValues[g_CustomInputValueIndex], 125.0f); + } + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} + +#pragma endregion + + +#pragma region Direct3D Resources + +// Constructor +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, DX::DeviceResources::c_Enable4K_UHD); +} + + +// Initialize the Direct3D resources required to run. +void Sample::Init(IUnknown* window) +{ + m_currentPaperWhiteNits = 100.0f; + m_countDownToBright = 5; + m_bShowOnlyPaperWhite = true; + m_bRender2084Curve = false; + m_current2084CurveRenderingNits = 500.0f; + + m_gamePad = std::make_unique(); + m_deviceResources->SetWindow(window); + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + m_deviceResources->CreateWindowSizeDependentResources(); + + CreateHDRSceneResources(); + Create2084CurveResources(); +} + + +// Create shaders, buffers, etc. for rendering 2084 curve +void Sample::Create2084CurveResources() +{ + auto d3dDevice = m_deviceResources->GetD3DDevice(); + auto pixelShaderBlob = DX::ReadData(L"PrepareSwapChainBuffersPS.cso"); + DX::ThrowIfFailed(d3dDevice->CreatePixelShader(pixelShaderBlob.data(), pixelShaderBlob.size(), nullptr, m_d3dPrepareSwapChainBuffersPS.ReleaseAndGetAddressOf())); + + // Point sampler + D3D11_SAMPLER_DESC samplerDesc; + ZeroMemory(&samplerDesc, sizeof(samplerDesc)); + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + DX::ThrowIfFailed(d3dDevice->CreateSamplerState(&samplerDesc, m_d3dPointSampler.ReleaseAndGetAddressOf())); + + // Constant buffer for setting nits for paper white + XMFLOAT4 data = { m_currentPaperWhiteNits, 0.0f, 0.0f, 0.0f }; + D3D11_SUBRESOURCE_DATA initData = { 0 }; + initData.pSysMem = &data; + + D3D11_BUFFER_DESC bufferDesc = { 0 }; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.ByteWidth = (sizeof(XMFLOAT4) + 15) & ~15; // has to be a multiple of 16 otherwise D3D is unhappy + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + DX::ThrowIfFailed(d3dDevice->CreateBuffer(&bufferDesc, &initData, m_d3dNitsForPaperWhiteCB.ReleaseAndGetAddressOf())); + m_d3dNitsForPaperWhiteCB->SetName(L"NitsForPaperWhite"); +} + + +// Create resource for HDR scene rendering, i.e. not the swapchains, etc. +void Sample::CreateHDRSceneResources() +{ + auto d3dDevice = m_deviceResources->GetD3DDevice(); + + auto outputSize = m_deviceResources->GetOutputSize(); + int width = outputSize.right - outputSize.left; + int height = outputSize.bottom - outputSize.top; + + auto pixelShaderBlob = DX::ReadData(L"ColorPS.cso"); + DX::ThrowIfFailed(d3dDevice->CreatePixelShader(pixelShaderBlob.data(), pixelShaderBlob.size(), nullptr, m_d3dColorPS.ReleaseAndGetAddressOf())); + + CD3D11_TEXTURE2D_DESC descTex(DXGI_FORMAT_R16G16B16A16_FLOAT, width, height, 1, 1, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); + DX::ThrowIfFailed(d3dDevice->CreateTexture2D(&descTex, nullptr, m_d3dHDRSceneTexture.ReleaseAndGetAddressOf())); + + CD3D11_RENDER_TARGET_VIEW_DESC descRTV(D3D11_RTV_DIMENSION_TEXTURE2D, descTex.Format); + DX::ThrowIfFailed(d3dDevice->CreateRenderTargetView(m_d3dHDRSceneTexture.Get(), &descRTV, m_d3dHDRSceneRTV.ReleaseAndGetAddressOf())); + + CD3D11_SHADER_RESOURCE_VIEW_DESC descSRV(D3D11_SRV_DIMENSION_TEXTURE2D, descTex.Format, 0, 1); + DX::ThrowIfFailed(d3dDevice->CreateShaderResourceView(m_d3dHDRSceneTexture.Get(), &descSRV, m_d3dHDRSceneSRV.ReleaseAndGetAddressOf())); +} + + +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_fullScreenQuad = std::make_unique(); + m_fullScreenQuad->Initialize(device); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + m_font = std::make_unique(device, L"Courier_36.spritefont"); + m_controllerFont = std::make_unique(device, L"XboxOneControllerLegendSmall.spritefont"); + m_spriteBatch = std::make_unique(context); + + m_states = std::make_unique(device); + m_lineEffect = std::make_unique(device); + m_lineEffect->SetVertexColorEnabled(true); + + void const* shaderByteCode; + size_t byteCodeLength; + m_lineEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); + DX::ThrowIfFailed(device->CreateInputLayout(VertexPositionColor::InputElements, VertexPositionColor::InputElementCount, shaderByteCode, byteCodeLength, m_inputLayout.ReleaseAndGetAddressOf())); + + m_primitiveBatch = std::make_unique>(context); + +} + +#pragma endregion + +#pragma region Message Handlers + +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} + +#pragma endregion + diff --git a/XDKSamples/Graphics/SimpleHDR/SimpleHDR.h b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.h new file mode 100644 index 0000000000000000000000000000000000000000..301df11c6125dc7ad8b007b6f2072299a977258f --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.h @@ -0,0 +1,122 @@ +//-------------------------------------------------------------------------------------- +// SimpleHDR.h +// +// This sample uses an API to determine if the attached display is HDR capable. If so, it +// will switch the display to HDR mode. A very simple HDR scene, with values above 1.0f, +// is rendered to a FP16 backbuffer and outputs to two different swapchains, one for HDR +// and one for SDR. Even if the consumer uses an HDR display, the SDR signal is still +// required for GameDVR and screenshots. +// +// Requirements for swapchain creation: +// 1) HDR swapchain has to be 10bit using DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 +// 2) SDR swapchain has to use DXGI_FORMAT_B8G8R8A8_UNORM_SRGB +// See DeviceResources.cpp for swapchain creation and presentation +// +// Refer to the white paper “HDR on Xbox One” +// +// Up to now, games were outputting and SDR signal using Rec.709 color primaries and Rec.709 +// gamma curve. One new feature of UHD displays is a wider color gamut (WCG). To use this +// we need to use a new color space, Rec.2020 color primaries. Another new feature of UHD +// displays is high dynamic range (HDR). To use this we need to use a different curve, the +// ST.2084 curve. Therefore, to output an HDR signal, it needs to use Rec.2020 color primaries +// with ST.2084 curve. +// +// For displaying the SDR signal, a simple tonemapping shader is applied to simply clip all +// values above 1.0f in the HDR scene, and outputs 8bit values using Rec.709 color primaries, +// with the gamma curve applied. +// +// For displaying the HDR signal, a shader is used to rotate the Rec.709 color primaries to +// Rec.2020 color primaries, and then apply the ST.2084 curve to output 10bit values which +// the HDR display can correctly display. The whiteness and brightness of the output on an +// HDR display will be determined by the selected nits value for defining “paper white”. +// SDR specs define “paper white” as 80nits, but this is for a cinema with a dark environment. +// Consumers today are used to much brighter whites, e.g. ~550 nits for a smartphone(so that it +// can be viewed in sunlight), 200-300 nits for a PC monitor, 120-150 nits for an SDR TV, etc. +// The nits for “paper white” can be adjusted in the sample using the DPad up/down. Displaying +// bright values next to white can be deceiving to the eye, so you can use the A button to +// toggle if you only want to see the “paper white” block. +// +// The sample has two modes: +// 1) Render blocks with specific values in the scene +// 2) Render ST.2084 curve with specific brightness values(nits) +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "FullScreenQuad\FullScreenQuad.h" + + +class Sample +{ +public: + Sample(); + void Initialize(IUnknown* window); + void Tick(); + void OnSuspending(); + void OnResuming(); + +private: + void Update(DX::StepTimer const& timer); + void Render(); + void Clear(); + void CreateDeviceDependentResources(); + void Init(IUnknown* window); + + // Standard sample defines + std::unique_ptr m_deviceResources; + uint64_t m_frame; + DX::StepTimer m_timer; + std::unique_ptr m_gamePad; + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_font; + std::unique_ptr m_controllerFont; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_states; + std::unique_ptr m_lineEffect; + Microsoft::WRL::ComPtr m_inputLayout; + std::unique_ptr> m_primitiveBatch; + std::unique_ptr m_fullScreenQuad; + + // HDR defines + void PrepareSwapChainBuffers(); // Takes as input the HDR scene values and outputs an HDR and SDR signal to two seperate swapchains + + std::atomic_bool m_bIsTVInHDRMode; // This will be set to TRUE if the attached display is in HDR mode + bool m_bRender2084Curve; // Render the ST.2084 curve rather than the HDR scene + bool m_bShowOnlyPaperWhite; // If enabled, only the block with value 1.0f (paper white) will be rendered. Seeing bright values next to white can have the effect of perceiving white as gray + double m_countDownToBright; // The countdown before rendering bright values at the start of the sample, so that eyes can adjust to what paper white looks like, to realize the difference between white and bright + float m_currentPaperWhiteNits; // Current brightness for paper white + + const int g_CustomInputValueIndex = 3; // Index of input values set by left/right sticks, others use fixed values + static const int NUM_INPUT_VALUES = 4; + float m_hdrSceneValues[NUM_INPUT_VALUES] = { 0.5f, 1.0f, 6.0f, 10.0f }; // Values that will be rendering to the HDR scene buffer + + // Rendering the HDR scene + Microsoft::WRL::ComPtr m_d3dColorPS; // Simple shader to output only color, useful to oupput very specific HDR color values + Microsoft::WRL::ComPtr m_d3dHDRSceneTexture; // HDR values will be rendered into this buffer + Microsoft::WRL::ComPtr m_d3dHDRSceneRTV; + Microsoft::WRL::ComPtr m_d3dHDRSceneSRV; + + float m_current2084CurveRenderingNits; // In the mode when rendering the curve, use this as the adjustable value indicated on the graph + + void CreateHDRSceneResources(); + void RenderHDRScene(); + void Render2084Curve(); + void RenderUI(); + + // Prepares HDR and SDR swapchain buffers + Microsoft::WRL::ComPtr m_d3dPointSampler; + Microsoft::WRL::ComPtr m_d3dPrepareSwapChainBuffersPS; // Outputs an HDR10 and GameDVR signal for the swapchain buffers to correctly be displayed in HDR and SDR displays + Microsoft::WRL::ComPtr m_d3dNitsForPaperWhiteCB; // Define the nit value of "paper white", e.g. 100 nits + + void Create2084CurveResources(); + + inline DirectX::XMVECTOR MakeColor(float value) { DirectX::XMVECTORF32 color = { value, value, value, 1.0f }; return color; } + +}; + diff --git a/XDKSamples/Graphics/SimpleHDR/SimpleHDR.sln b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.sln new file mode 100644 index 0000000000000000000000000000000000000000..42f65b3ef8cf1a8fe11c9b37c90abde909a969cf --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleHDR", "SimpleHDR.vcxproj", "{00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Debug|Durango.ActiveCfg = Debug|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Debug|Durango.Build.0 = Debug|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Debug|Durango.Deploy.0 = Debug|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Profile|Durango.ActiveCfg = Profile|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Profile|Durango.Build.0 = Profile|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Profile|Durango.Deploy.0 = Profile|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Release|Durango.ActiveCfg = Release|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Release|Durango.Build.0 = Release|Durango + {00BEE4F4-A383-4BC0-B106-44CA1D2F1ED3}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Graphics/SimpleHDR/SimpleHDR.vcxproj b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6e49e1be3d03413e1e709f547f5247aeccbac0bc --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.vcxproj @@ -0,0 +1,260 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleHDR + {00bee4f4-a383-4bc0-b106-44ca1d2f1ed3} + en-US + Win32Proj + title + + v140 + 11.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\ATGTK\HDR;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + ..\..\..\Kits\ATGTK\HDR\;%(AdditionalIncludeDirectories) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\ATGTK\HDR;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + ..\..\..\Kits\ATGTK\HDR\;%(AdditionalIncludeDirectories) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\ATGTK\HDR;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + ..\..\..\Kits\ATGTK\HDR\;%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + Designer + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + true + true + true + + + true + true + true + + + + + + Pixel + Pixel + Pixel + main11 + main11 + main11 + + + Vertex + Vertex + Vertex + main11 + main11 + main11 + + + Pixel + Pixel + Pixel + + + Pixel + Pixel + Pixel + main + main + main + + + + + + \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR/SimpleHDR.vcxproj.filters b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..77d3cc5d3100ee95018dd4aa1409dfb78700716e --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/SimpleHDR.vcxproj.filters @@ -0,0 +1,124 @@ + + + + + {a7c77edd-e4e7-4c73-b35e-7455b9200831} + + + 4f02342f-3a2e-4419-a816-fc85ab5b67c8 + + + f467ecf4-a3fa-4357-b6f4-4e7922757dfc + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {bf28dce9-df18-413e-a6b6-d90d98217969} + + + {e02a8552-6067-4c88-9f5c-91543b4da006} + + + {87eb472a-5f22-41a3-87e8-ad26de2bf8c0} + + + {15065ebc-b5e7-454d-a857-0cc0d10931ca} + + + + + Standard Sample Files + + + Standard Sample Files\ATG Tool Kit + + + HDR + + + HDR + + + Standard Sample Files\Common + + + Standard Sample Files\Common + + + Standard Sample Files\ATG Tool Kit + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + + + Standard Sample Files + + + Standard Sample Files + + + HDR + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + + + Standard Sample Files\Assets + + + + Standard Sample Files\Assets + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + + + Standard Sample Files\Shaders + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + + + Standard Sample Files + + + \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR/StepTimer.h b/XDKSamples/Graphics/SimpleHDR/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Graphics/SimpleHDR/Telemetry.h b/XDKSamples/Graphics/SimpleHDR/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Graphics/SimpleHDR/pch.cpp b/XDKSamples/Graphics/SimpleHDR/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Graphics/SimpleHDR/pch.h b/XDKSamples/Graphics/SimpleHDR/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..064d6b01093a3955949b34f931fa48a960ac59c6 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR/pch.h @@ -0,0 +1,73 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A04AA /* XDK Edition: 160300 */ +#error This sample requires the March 2016 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "CommonStates.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "PrimitiveBatch.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "VertexTypes.h" + + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/Assets/Logo.png b/XDKSamples/Graphics/SimpleHDR12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR12/Assets/Logo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR12/Assets/SmallLogo.png b/XDKSamples/Graphics/SimpleHDR12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR12/Assets/SmallLogo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR12/Assets/SplashScreen.png b/XDKSamples/Graphics/SimpleHDR12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR12/Assets/SplashScreen.png differ diff --git a/XDKSamples/Graphics/SimpleHDR12/Assets/StoreLogo.png b/XDKSamples/Graphics/SimpleHDR12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR12/Assets/StoreLogo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR12/Assets/WideLogo.png b/XDKSamples/Graphics/SimpleHDR12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR12/Assets/WideLogo.png differ diff --git a/XDKSamples/Graphics/SimpleHDR12/ColorPS.hlsl b/XDKSamples/Graphics/SimpleHDR12/ColorPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..4d089d99b1affea0877caef79d055556742ff417 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/ColorPS.hlsl @@ -0,0 +1,16 @@ +//-------------------------------------------------------------------------------------- +// ColorPS.hlsl +// +// A custom pixel shader for SpriteBatch that only outputs color +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "RootSig.fxh" + +[RootSignature(SpriteStaticRS)] +float4 main(float4 color : COLOR) : SV_Target0 +{ + return color; +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/DeviceResources.cpp b/XDKSamples/Graphics/SimpleHDR12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85671bcd36cbe40ea91cf23e60ba8239e1145f96 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/DeviceResources.cpp @@ -0,0 +1,458 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// +// NOTE: This is a customized version of DeviceResources.cpp that has specific implementation for HDR swapchain creation +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT gameDVRFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat(gameDVRFormat) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount * RTVDescriptors::Count; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorHeap->SetName(L"DeviceResources"); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_dsvDescriptorHeap->SetName(L"DeviceResources"); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargetsHDR10[n].Reset(); + m_renderTargetsGameDVR[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChainHDR10) + { + // HDR: If the HDR10 swap chain already exists, resize it. + ThrowIfFailed(m_swapChainHDR10->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + DXGI_FORMAT_R10G10B10A2_UNORM, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // HDR: Create HDR10 swapchain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // HDR: HDR10 swapchain must be 10:10:10:2. + swapChainDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + + // HDR: The HDR10 swapchain buffer needs to use the ST.2084 curve with Rec.2020 color primaries. + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084; + + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChainHDR10.ReleaseAndGetAddressOf() + )); + } + + if (m_swapChainGameDVR) + { + // HDR: If the GameDVR SDR swap chain already exists, resize it. + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // HDR: Create GameDVR SDR swpachain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // HDR: GameDVR SDR swapchain can be 8:8:8:8, 8:8:8:8_SRGB, or 10:10:10:2. + swapChainDesc.Format = m_gameDVRFormat; + + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + // HDR: Create a render target view of the HDR10 swap chain back buffer. + ThrowIfFailed(m_swapChainHDR10->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargetsHDR10[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"HDR10 Render target %u", n); + m_renderTargetsHDR10[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorHDR10(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), (n * RTVDescriptors::Count) + RTVDescriptors::HDR10, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargetsHDR10[n].Get(), &rtvDesc, rtvDescriptorHDR10); + + // HDR: Create a render target view of the GameDVR SDR swap chain back buffer. + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); + + swprintf_s(name, L"GameDVR Render target %u", n); + m_renderTargetsGameDVR[n]->SetName(name); + + rtvDesc.Format = m_gameDVRFormat; + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), (n * RTVDescriptors::Count) + RTVDescriptors::GameDVR, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsHDR10[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET) + }; + m_commandList->ResourceBarrier(_countof(barriers), barriers); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState, bool isTVInHDRMode) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsHDR10[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT) + }; + m_commandList->ResourceBarrier(_countof(barriers), barriers); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + if (isTVInHDRMode) + { + // When TV is in HDR mode, we present two swapchain buffers, one for HDR10 and the other an SDR image for GameDVR/screenshots + IDXGISwapChain1* ppSwapChains[2] = { m_swapChainHDR10.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1] = presentParameterSets[0]; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChainGameDVR->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/Graphics/SimpleHDR12/DeviceResources.h b/XDKSamples/Graphics/SimpleHDR12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..aaf3afc7cfa241cffd954ef2428f2c13025918cb --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/DeviceResources.h @@ -0,0 +1,129 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// +// NOTE: This is a customized version of DeviceResources.cpp that has specific implementation for HDR swapchain creation +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT gameDVRFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET, bool isTVInHDRMode = false); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Descriptors for m_rtvDescriptorHeap + enum RTVDescriptors + { + HDR10, + GameDVR, + Count + }; + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Direct3D HDR10 swapchain. + IDXGISwapChain1* GetHDR10SwapChain() const { return m_swapChainHDR10.Get(); } + ID3D12Resource* GetHDR10RenderTarget() const { return m_renderTargetsHDR10[m_backBufferIndex].Get(); } + DXGI_FORMAT GetHDR10BackBufferFormat() const { return DXGI_FORMAT_R10G10B10A2_UNORM; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetHDR10RenderTargetView() const + { // Heap containst: HDR10[m_backBufferIndex], GameDVR[m_backBufferIndex], HDR10[m_backBufferIndex + 1], GameDVR[m_backBufferIndex + 1], ... + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), (m_backBufferIndex * RTVDescriptors::Count) + RTVDescriptors::HDR10, m_rtvDescriptorSize); + } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D12Resource* GetGameDVRRenderTarget() const { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const + { // Heap containst: HDR10[m_backBufferIndex], GameDVR[m_backBufferIndex], HDR10[m_backBufferIndex + 1], GameDVR[m_backBufferIndex + 1], ... + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), (m_backBufferIndex * RTVDescriptors::Count) + RTVDescriptors::GameDVR, m_rtvDescriptorSize); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR10 swapchain. + Microsoft::WRL::ComPtr m_swapChainHDR10; + Microsoft::WRL::ComPtr m_renderTargetsHDR10[MAX_BACK_BUFFER_COUNT]; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; + DXGI_FORMAT m_gameDVRFormat; + }; +} diff --git a/XDKSamples/Graphics/SimpleHDR12/Main.cpp b/XDKSamples/Graphics/SimpleHDR12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7341a7135c3fe9970d91ad1a36d406ee7df1be35 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleHDR12.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/Package.appxmanifest b/XDKSamples/Graphics/SimpleHDR12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..7eb5d14ad1e8f24c87d6d5121aa2ca1f75035bde --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleHDR (DirectX 12) + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleHDR for DirectX 12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Graphics/SimpleHDR12/PrepareSwapChainBuffersPS.hlsl b/XDKSamples/Graphics/SimpleHDR12/PrepareSwapChainBuffersPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..8fced50344f2ee6a6da8474ef73936a3007e9b5a --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/PrepareSwapChainBuffersPS.hlsl @@ -0,0 +1,58 @@ +//-------------------------------------------------------------------------------------- +// PrepareSwapChainBuffersPS.hlsl +// +// Takes the final HDR back buffer with linear values using Rec.709 color primaries and +// outputs two signals, an HDR and SDR signal. The HDR siganl uses Rec.2020 color primaries +// with the ST.2084 curve, whereas the SDR signal uses Rec.709 color primaries which the +// hardware will apply the Rec.709 gamma curve. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "HDRCommon.hlsli" +#include "FullScreenQuad.hlsli" + + +cbuffer HDR10Data : register(b0) +{ + float PaperWhiteNits; // Defines how bright white is (in nits), which controls how bright the SDR range in the image will be, e.g. 200 nits +}; + + + +// Very simple HDR to SDR tonemapping, which simply clips values above 1.0f from the HDR scene. +float4 TonemapHDR2SDR(float4 hdrSceneValue) +{ + return saturate(hdrSceneValue); +} + +struct Interpolants +{ + float4 color : COLOR; + float2 texCoord : TEXCOORD; +}; + +struct PSOut +{ + float4 HDR10 : SV_Target0; // HDR10 buffer using Rec.2020 color primaries with ST.2084 curve + float4 GameDVR : SV_Target1; // GameDVR buffer using Rec.709 color primaries with sRGB gamma curve +}; + +// Prepare the HDR swapchain buffer as HDR10. This means the buffer has to contain data which uses +// - Rec.2020 color primaries +// - Quantized using ST.2084 curve +// - 10-bit per channel +[RootSignature(FullScreenQuadRS)] +PSOut main(Interpolators In) +{ + PSOut output; + + // Input is linear values using sRGB / Rec.709 color primaries + float4 hdrSceneValues = Texture.Sample(PointSampler, In.TexCoord); + + output.HDR10 = ConvertToHDR10(hdrSceneValues, PaperWhiteNits.x); + output.GameDVR = TonemapHDR2SDR(hdrSceneValues); + + return output; +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/Readme.docx b/XDKSamples/Graphics/SimpleHDR12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..9764ad39e2744fb47fde6e2f348f489b35e54ee9 Binary files /dev/null and b/XDKSamples/Graphics/SimpleHDR12/Readme.docx differ diff --git a/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.cpp b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9f5c9c4aca64685b85f0ec6adb656671ff81125 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.cpp @@ -0,0 +1,861 @@ +//-------------------------------------------------------------------------------------- +// SimpleHDR12.cpp +// +// This sample uses an API to determine if the attached display is HDR capable. If so, it +// will switch the display to HDR mode. A very simple HDR scene, with values above 1.0f, +// is rendered to a FP16 backbuffer and outputs to two different swapchains, one for HDR +// and one for SDR. Even if the consumer uses an HDR display, the SDR signal is still +// required for GameDVR and screenshots. +// +// Requirements for swapchain creation: +// 1) HDR swapchain has to be DXGI_FORMAT_R10G10B10A2_UNORM +// 2) HDR swapchain has to use XGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 +// +// See DeviceResources.cpp for swapchain creation and presentation +// +// Refer to the white paper “HDR on Xbox One” +// +// Up to now, games were outputting and SDR signal using Rec.709 color primaries and Rec.709 +// gamma curve. One new feature of UHD displays is a wider color gamut (WCG). To use this +// we need to use a new color space, Rec.2020 color primaries. Another new feature of UHD +// displays is high dynamic range (HDR). To use this we need to use a different curve, the +// ST.2084 curve. Therefore, to output an HDR signal, it needs to use Rec.2020 color primaries +// with ST.2084 curve. +// +// For displaying the SDR signal, a simple tonemapping shader is applied to simply clip all +// values above 1.0f in the HDR scene, and outputs 8bit values using Rec.709 color primaries, +// with the gamma curve applied. +// +// For displaying the HDR signal, a shader is used to rotate the Rec.709 color primaries to +// Rec.2020 color primaries, and then apply the ST.2084 curve to output 10bit values which +// the HDR display can correctly display. The whiteness and brightness of the output on an +// HDR display will be determined by the selected nits value for defining “paper white”. +// SDR specs define “paper white” as 80nits, but this is for a cinema with a dark environment. +// Consumers today are used to much brighter whites, e.g. ~550 nits for a smartphone(so that it +// can be viewed in sunlight), 200-300 nits for a PC monitor, 120-150 nits for an SDR TV, etc. +// The nits for “paper white” can be adjusted in the sample using the DPad up/down. Displaying +// bright values next to white can be deceiving to the eye, so you can use the A button to +// toggle if you only want to see the “paper white” block. +// +// The sample has two modes: +// 1) Render blocks with specific values in the scene +// 2) Render ST.2084 curve with specific brightness values(nits) +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleHDR12.h" +#include "HDRCommon.h" +#include "ControllerFont.h" +#include +#include "ReadData.h" + + +extern void ExitSample(); + +using namespace DX; +using namespace DirectX; +using namespace SimpleMath; +using namespace Colors; +using Microsoft::WRL::ComPtr; + + +#pragma region HDR + +// Initialize, including trying to set the display to HDR mode +void Sample::Initialize(IUnknown* window) +{ + m_bIsTVInHDRMode = false; + + // Determine if attached display is HDR or SDR, if HDR, also set the TV in HDR mode. This is an async operation, + // so we can do other initalizations in the meanwhile + auto determineHDRAction = Windows::Xbox::Graphics::Display::DisplayConfiguration::TrySetHdrModeAsync(); + auto determineHDRTask = Concurrency::create_task(determineHDRAction); + + m_hdrScene = std::make_unique(DXGI_FORMAT_R16G16B16A16_FLOAT); + m_hdrScene->SetClearColor(Black); + + // Regular sample initialization + Init(window); + + // Now wait until we know if display is in HDR mode + try + { + // .get() will automatically .wait() until the async operation is done + auto results = determineHDRTask.get(); + m_bIsTVInHDRMode = results->HdrEnabled; + } + catch (Platform::Exception^ e) + { + OutputDebugStringW(e->Message->Data()); + throw; + } +} + + +// Render +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto d3dCommandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(d3dCommandList, PIX_COLOR_DEFAULT, L"Render"); + + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptorHeap->Heap() }; + d3dCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + if (m_bRender2084Curve) + { + // Render the ST.2084 curve + Render2084Curve(); + } + else + { + // Render the HDR scene with values larger than 1.0f, which will be perceived as bright + RenderHDRScene(); + } + + // Render the UI with values of 1.0f, which will be perceived as white + RenderUI(); + + // Process the HDR scene so that the swapchains can correctly be sent to HDR or SDR display + PrepareSwapChainBuffers(); + + PIXEndEvent(d3dCommandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(D3D12_RESOURCE_STATE_RENDER_TARGET, m_bIsTVInHDRMode); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + + +// Process the HDR scene so that the swapchains can correctly be sent to HDR or SDR display +void Sample::PrepareSwapChainBuffers() +{ + auto d3dCommandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(d3dCommandList, PIX_COLOR_DEFAULT, L"PrepareSwapChainBuffers"); + + // We need to sample from the HDR backbuffer + m_hdrScene->TransitionTo(d3dCommandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + // Set RTVs + D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor[2] = {m_deviceResources->GetHDR10RenderTargetView(), m_deviceResources->GetGameDVRRenderTargetView() }; + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + d3dCommandList->OMSetRenderTargets(2, rtvDescriptor, FALSE, &dsvDescriptor); + + // Update constant buffer and render + auto hdr10Data = m_graphicsMemory->AllocateConstant(m_HDR10Data); + auto hdrSRV = m_resourceDescriptorHeap->GetGpuHandle(static_cast(ResourceDescriptors::HDRScene)); + m_fullScreenQuad->Draw(d3dCommandList, m_d3dPrepareSwapChainBufferPSO.Get(), hdrSRV, hdr10Data.GpuAddress()); + + PIXEndEvent(d3dCommandList); +} + + +// Clamp value between 0 and 1 +inline float Clamp(float value) +{ + return std::min(std::max(value, 0.0f), 1.0f); +} + +// Applies the sRGB gamma curve to a linear value. This function is only used to output UI values +float LinearToSRGB(float hdrSceneValue) +{ + const float Cutoff = 0.0031308f; + const float Linear = 12.92f; + const float Scale = 1.055f; + const float Bias = 0.055f; + const float Gamma = 2.4f; + const float InvGamma = 1.0f / Gamma; + + // clamp values [0..1] + hdrSceneValue = Clamp(hdrSceneValue); + + // linear piece for dark values + if (hdrSceneValue < Cutoff) + { + return hdrSceneValue * Linear; + } + + return Scale * std::pow(hdrSceneValue, InvGamma) - Bias; +} + + +// Render the HDR scene with four squares, each with a different HDR value. Values larger than 1.0f will be perceived as bright +void Sample::RenderHDRScene() +{ + auto d3dCommandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(d3dCommandList, PIX_COLOR_DEFAULT, L"RenderHDRScene"); + + auto viewportUI = m_deviceResources->GetScreenViewport(); + viewportUI.Width = 1920; + viewportUI.Height = 1080; + m_spriteBatch->SetViewport(viewportUI); + m_fontBatch->SetViewport(viewportUI); + + const long step = static_cast(1920.0f / (NUM_INPUT_VALUES + 2.0f)); + + float startX = 115; + + // SpriteBatch requires a texture, otherwise it will assert, but we just want to draw a color, so give it a dummy texture + XMUINT2 dummyTextureSize = { 1, 1 }; + auto dummyTexture = m_resourceDescriptorHeap->GetGpuHandle(static_cast(ResourceDescriptors::HDRScene)); + + RECT position = { 0 }; + position.left = static_cast(startX); + + // Render each block with the specific HDR scene value + for (int i = 0; i < NUM_INPUT_VALUES; i++) + { + XMVECTOR hdrSceneColor = MakeColor(m_hdrSceneValues[i]); + + m_spriteBatch->Begin(d3dCommandList, SpriteSortMode_Immediate); + + position.left += step; + position.top = 485; + position.right = position.left + static_cast(step / 1.25f); + position.bottom = position.top + 250; + + if (!m_bShowOnlyPaperWhite) + { + m_spriteBatch->Draw(dummyTexture, dummyTextureSize, position, hdrSceneColor); + } + else if (XMVector2Equal(hdrSceneColor, White)) + { + m_spriteBatch->Draw(dummyTexture, dummyTextureSize, position, hdrSceneColor); + } + + m_spriteBatch->End(); + } + + // Render the text + wchar_t strText[2048] = {}; + const float startY = 40.0f; + const float fontScale = 0.75f; + + Vector2 fontPos; + + startX = 50.0f; + + m_fontBatch->Begin(d3dCommandList); + + fontPos.x = startX; + fontPos.y = startY + 270.0f; + m_textFont->DrawString(m_fontBatch.get(), L"HDR Scene Values", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + m_textFont->DrawString(m_fontBatch.get(), L"SDR sRGB Curve", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + m_textFont->DrawString(m_fontBatch.get(), L"HDR ST.2084 Curve", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + m_textFont->DrawString(m_fontBatch.get(), L"HDR Nits Output", fontPos, White, 0.0f, g_XMZero, fontScale); + + fontPos.x = startX + 100.0f; + + for (int i = 0; i < NUM_INPUT_VALUES; i++) + { + float hdrSceneValue = m_hdrSceneValues[i]; + float sdrGamma = LinearToSRGB(hdrSceneValue); + float hdr2084 = LinearToST2084(hdrSceneValue, m_HDR10Data.PaperWhiteNits); + float hdrNits = CalcNits(hdrSceneValue, m_HDR10Data.PaperWhiteNits); + + fontPos.x += step; + fontPos.y = startY + 270.0f; + swprintf_s(strText, L"%f", hdrSceneValue); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + swprintf_s(strText, L"%f", sdrGamma); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + swprintf_s(strText, L"%f", hdr2084); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + swprintf_s(strText, L"%f", hdrNits); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.y += 40; + } + + fontPos.y = startY + 700.0f; + fontPos.x = startX + 100.0f + step + step - 15.0f; + m_textFont->DrawString(m_fontBatch.get(), L"Paper White", fontPos, White, 0.0f, g_XMZero, fontScale); fontPos.x += step + 45; + + if (!m_bShowOnlyPaperWhite) + { + m_textFont->DrawString(m_fontBatch.get(), L"Bright", fontPos, White, 0.0f, g_XMZero, fontScale); + } + + m_fontBatch->End(); + + PIXEndEvent(d3dCommandList); +} + + +// Render the ST.2084 curve +void Sample::Render2084Curve() +{ + auto d3dCommandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(d3dCommandList, PIX_COLOR_DEFAULT, L"Render2084Curve"); + + auto outputSize = m_deviceResources->GetOutputSize(); + float scale = (outputSize.bottom - outputSize.top) / 1080.0f; + + float viewportWidth = 1675 * scale; + float viewportHeight = 600 * scale; + float startX = 150.0f; + float startY = 250.0f; + + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + + viewport.TopLeftX = startX * scale; + viewport.TopLeftY = startY * scale; + viewport.Width = viewportWidth; + viewport.Height = viewportHeight; + + scissorRect.left = static_cast(viewport.TopLeftX); + scissorRect.top = static_cast(viewport.TopLeftY); + scissorRect.right = static_cast(scissorRect.left + viewport.Width); + scissorRect.bottom = static_cast(scissorRect.top + viewport.Height); + + d3dCommandList->RSSetViewports(1, &viewport); + d3dCommandList->RSSetScissorRects(1, &scissorRect); + + Matrix proj = Matrix::CreateOrthographicOffCenter(0.0f, viewportWidth, viewportHeight, 0.0f, 0.0f, 1.0f); + + m_lineEffect->SetProjection(proj); + m_lineEffect->Apply(d3dCommandList); + m_primitiveBatch->Begin(d3dCommandList); + + // Render the outline + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(0.5f, 0.5f, 0), White), VertexPositionColor(Vector3(viewportWidth, 0.5f, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(0.5f, viewportHeight, 0), White), VertexPositionColor(Vector3(viewportWidth, viewportHeight, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(0.5f, 0.5f, 0), White), VertexPositionColor(Vector3(0.5f, viewportHeight, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(viewportWidth, 0.5f, 0), White), VertexPositionColor(Vector3(viewportWidth, viewportHeight, 0), White)); + + // Render horizontal tick marks + float numSteps = 16; + for (int i = 0; i < numSteps; i++) + { + float x = (i * (viewportWidth / numSteps)) + 0.5f; + float y = viewportHeight; + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, y, 0), White), VertexPositionColor(Vector3(x, y - 10, 0), White)); + } + + // Render the graph + for (int i = 0; i < viewportWidth; i++) + { + float x1 = static_cast(i) + 0.5f; + float normalizedLinearValue = static_cast(i) / viewportWidth; + float normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + float y1 = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + float x2 = x1 + 1; + normalizedLinearValue = static_cast(x2) / viewportWidth; + normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + float y2 = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x1, y1, 0), White), VertexPositionColor(Vector3(x2, y2, 0), White)); + } + + // Render the lines indication the current selection + float normalizedLinearValue = m_current2084CurveRenderingNits / g_MaxNitsFor2084; + float normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + float x = normalizedLinearValue * viewportWidth; + float y = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, viewportHeight, 0), White), VertexPositionColor(Vector3(x, y, 0), White)); + m_primitiveBatch->DrawLine(VertexPositionColor(Vector3(x, y, 0), White), VertexPositionColor(Vector3(0, y, 0), White)); + + m_primitiveBatch->End(); + + // Restore viewport + viewport = m_deviceResources->GetScreenViewport(); + scissorRect = m_deviceResources->GetScissorRect(); + d3dCommandList->RSSetViewports(1, &viewport); + d3dCommandList->RSSetScissorRects(1, &scissorRect); + + auto viewportUI = m_deviceResources->GetScreenViewport(); + viewportUI.Width = 1920; + viewportUI.Height = 1080; + m_fontBatch->SetViewport(viewportUI); + m_spriteBatch->SetViewport(viewportUI); + + // Render text + viewportWidth /= scale; + viewportHeight /= scale; + + wchar_t strText[2048] = {}; + Vector2 fontPos; + m_fontBatch->Begin(d3dCommandList); + + fontPos.x = startX - 100; + fontPos.y = startY + viewportHeight + 5; + m_textFont->DrawString(m_fontBatch.get(), L"Linear", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + m_textFont->DrawString(m_fontBatch.get(), L"Nits", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + m_textFont->DrawString(m_fontBatch.get(), L"HDR Scene", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + + fontPos.x = startX + viewportWidth - 5; + fontPos.y = startY + viewportHeight + 5; + m_textFont->DrawString(m_fontBatch.get(), L"1.0", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; // Always [0..1] + m_textFont->DrawString(m_fontBatch.get(), L"10K", fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; // Spec defines 10K nits + + // Max HDR scene value changes as white paper nits change + float hdrSceneValue = CalcHDRSceneValue(g_MaxNitsFor2084, m_HDR10Data.PaperWhiteNits); + swprintf_s(strText, L"%1.0f", hdrSceneValue); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + + normalizedLinearValue = m_current2084CurveRenderingNits / g_MaxNitsFor2084; + normalizedNonLinearValue = LinearToST2084(normalizedLinearValue); + hdrSceneValue = CalcHDRSceneValue(m_current2084CurveRenderingNits, m_HDR10Data.PaperWhiteNits); + + x = normalizedLinearValue * viewportWidth + 1; + y = viewportHeight - (normalizedNonLinearValue * viewportHeight); + + fontPos.x = startX + x; + fontPos.y = startY + viewportHeight + 5; + swprintf_s(strText, L"%1.2f", normalizedLinearValue); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + swprintf_s(strText, L"%1.0f", m_current2084CurveRenderingNits); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + swprintf_s(strText, L"%1.2f", hdrSceneValue); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.y += 20; + + fontPos.x = startX - 25; + fontPos.y = startY - 50; + m_textFont->DrawString(m_fontBatch.get(), L"ST.2084", fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); fontPos.x -= 20; + m_textFont->DrawString(m_fontBatch.get(), L"Nits", fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); + + fontPos.x = startX - 25; + fontPos.y = y + startY; + swprintf_s(strText, L"%1.2f", normalizedNonLinearValue); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); fontPos.x -= 20; + swprintf_s(strText, L"%1.0f", m_current2084CurveRenderingNits); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); + + m_fontBatch->End(); + + // Render blocks + const long size = 150; + RECT position = { 0 }; + position.left = 1920 - size * 4; + position.top = 50; + position.right = position.left + size; + position.bottom = position.top + size; + + // SpriteBatch requires a texture, otherwise it will assert, but we just want to draw a color, so give it a dummy texture + XMUINT2 dummyTextureSize = { 1, 1 }; + auto dummyTexture = m_resourceDescriptorHeap->GetGpuHandle(static_cast(ResourceDescriptors::HDRScene)); + + m_spriteBatch->Begin(d3dCommandList, SpriteSortMode_Immediate); + m_spriteBatch->Draw(dummyTexture, dummyTextureSize, position, White); + + position.left += size * 2; + position.right = position.left + size; + + XMVECTORF32 color = { hdrSceneValue, hdrSceneValue, hdrSceneValue, 1.0f }; + m_spriteBatch->Draw(dummyTexture, dummyTextureSize, position, color); + + m_spriteBatch->End(); + + // Render text for blocks + m_fontBatch->Begin(d3dCommandList); + + fontPos.x = 1920 - size * 4 - 25; + fontPos.y = static_cast(position.bottom - 15); + + m_textFont->DrawString(m_fontBatch.get(), L"Paper White", fontPos, White, -XM_PIDIV2, g_XMZero, 0.4f); + + fontPos.x = 1920 - size * 4 + 25; + fontPos.y = static_cast(position.bottom); + + swprintf_s(strText, L"%1.0f nits", m_HDR10Data.PaperWhiteNits); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); fontPos.x += size * 2; + swprintf_s(strText, L"%1.0f nits", m_current2084CurveRenderingNits); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 0.4f); + + m_fontBatch->End(); + + PIXEndEvent(d3dCommandList); +} + + +// Render the UI +void Sample::RenderUI() +{ + auto d3dCommandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(d3dCommandList, PIX_COLOR_DEFAULT, L"RenderUI"); + + auto viewportUI = m_deviceResources->GetScreenViewport(); + viewportUI.Width = 1920; + viewportUI.Height = 1080; + m_fontBatch->SetViewport(viewportUI); + + const float startX = 50.0f; + const float startY = 40.0f; + const float fontScale = 0.75f; + + Vector2 fontPos(startX, startY); + + m_fontBatch->Begin(d3dCommandList); + m_textFont->DrawString(m_fontBatch.get(), L"SimpleHDR Sample for DirectX 12", fontPos, White, 0.0f, g_XMZero, 1.0f); + + if (!m_bRender2084Curve) + { + fontPos.y = startY + 100.0f; + if (m_bIsTVInHDRMode) + { + m_textFont->DrawString(m_fontBatch.get(), L"TV in HDR Mode: TRUE", fontPos, White, 0.0f, g_XMZero, fontScale); + } + else + { + m_textFont->DrawString(m_fontBatch.get(), L"TV in HDR Mode: FALSE", fontPos, White, 0.0f, g_XMZero, fontScale); + } + } + + fontPos.x = startX; + fontPos.y = 955; + DX::DrawControllerString(m_fontBatch.get(), m_textFont.get(), m_controllerFont.get(), L"[A] - Toggle displaying ST.2084 curve", fontPos, White, 0.65f); fontPos.y += 35; + DX::DrawControllerString(m_fontBatch.get(), m_textFont.get(), m_controllerFont.get(), L"[B] - Toggle displaying only paper white block", fontPos, White, 0.65f); fontPos.y += 35; + + fontPos.x = (1920.0f/2.0f) + startX; + fontPos.y = 955; + DX::DrawControllerString(m_fontBatch.get(), m_textFont.get(), m_controllerFont.get(), L"[DPad] - Adjust paper white nits", fontPos, White, 0.65f); fontPos.y += 35; + DX::DrawControllerString(m_fontBatch.get(), m_textFont.get(), m_controllerFont.get(), L"[LThumb] - Adjust values quickly", fontPos, White, 0.65f); fontPos.y += 35; + DX::DrawControllerString(m_fontBatch.get(), m_textFont.get(), m_controllerFont.get(), L"[RThumb] - Adjust values slowly", fontPos, White, 0.65f); fontPos.y += 35; + + if (m_countDownToBright >= 0) + { + fontPos.x = 1170; + fontPos.y = 550; + + wchar_t strText[2048] = {}; + swprintf_s(strText, L"%1.0f", m_countDownToBright); + m_textFont->DrawString(m_fontBatch.get(), strText, fontPos, White, 0.0f, g_XMZero, 1.75f); + } + + m_fontBatch->End(); + + PIXEndEvent(d3dCommandList); +} + +#pragma endregion + +#pragma region Frame Update + +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + static bool bCountingDownToBright = true; + m_countDownToBright -= timer.GetElapsedSeconds(); + if (bCountingDownToBright && (m_countDownToBright < 0)) + { + bCountingDownToBright = false; + m_bShowOnlyPaperWhite = false; + } + + auto gamepad = m_gamePad->GetState(0); + + if (gamepad.IsConnected()) + { + if (gamepad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + m_gamePadButtons.Update(gamepad); + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_bRender2084Curve = !m_bRender2084Curve; + } + + if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + m_bShowOnlyPaperWhite = !m_bShowOnlyPaperWhite; + } + + if (m_gamePadButtons.dpadDown == GamePad::ButtonStateTracker::PRESSED || + m_gamePadButtons.dpadLeft == GamePad::ButtonStateTracker::PRESSED) + { + m_HDR10Data.PaperWhiteNits -= 20.0f;; + m_HDR10Data.PaperWhiteNits = std::max(m_HDR10Data.PaperWhiteNits, 80.0f); + } + + if (m_gamePadButtons.dpadUp == GamePad::ButtonStateTracker::PRESSED || + m_gamePadButtons.dpadRight == GamePad::ButtonStateTracker::PRESSED) + { + m_HDR10Data.PaperWhiteNits += 20.0f; + m_HDR10Data.PaperWhiteNits = std::min(m_HDR10Data.PaperWhiteNits, g_MaxNitsFor2084); + } + + const float fastNitsDelta = 25.0f; + const float slowNitsDelta = 1.0f; + const float fastSceneValueDelta = 0.05f; + const float slowSceneValueDelta = 0.005f; + + if (gamepad.IsLeftThumbStickDown() || gamepad.IsLeftThumbStickLeft()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits -= fastNitsDelta; + m_current2084CurveRenderingNits = std::max(m_current2084CurveRenderingNits, 0.0f); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] -= fastSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::max(m_hdrSceneValues[g_CustomInputValueIndex], 0.0f); + } + } + + if ( gamepad.IsRightThumbStickDown() || gamepad.IsRightThumbStickLeft()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits -= slowNitsDelta; + m_current2084CurveRenderingNits = std::max(m_current2084CurveRenderingNits, 0.0f); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] -= slowSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::max(m_hdrSceneValues[g_CustomInputValueIndex], 0.0f); + } + } + + if (gamepad.IsLeftThumbStickUp() || gamepad.IsLeftThumbStickRight()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits += fastNitsDelta; + m_current2084CurveRenderingNits = std::min(m_current2084CurveRenderingNits, g_MaxNitsFor2084); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] += fastSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::min(m_hdrSceneValues[g_CustomInputValueIndex], 125.0f); + } + } + + if (gamepad.IsRightThumbStickUp() || gamepad.IsRightThumbStickRight()) + { + if (m_bRender2084Curve) + { + m_current2084CurveRenderingNits += slowNitsDelta; + m_current2084CurveRenderingNits = std::min(m_current2084CurveRenderingNits, g_MaxNitsFor2084); + } + else + { + m_hdrSceneValues[g_CustomInputValueIndex] += slowSceneValueDelta; + m_hdrSceneValues[g_CustomInputValueIndex] = std::min(m_hdrSceneValues[g_CustomInputValueIndex], 125.0f); + } + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Direct3D Resources + +Sample::Sample() : + m_frame(0) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Init(IUnknown* window) +{ + m_HDR10Data.PaperWhiteNits = 100.0f; + m_countDownToBright = 5; + m_bShowOnlyPaperWhite = true; + m_bRender2084Curve = false; + m_current2084CurveRenderingNits = 500.0f; + + m_gamePad = std::make_unique(); + m_deviceResources->SetWindow(window); + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + CreateWindowSizeDependentResources(); + m_deviceResources->CreateWindowSizeDependentResources(); +} + + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto d3dCommandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(d3dCommandList, PIX_COLOR_DEFAULT, L"Clear"); + + m_hdrScene->TransitionTo(d3dCommandList, D3D12_RESOURCE_STATE_RENDER_TARGET); + + auto rtvDescriptor = m_rtvDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::HDRScene)); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + d3dCommandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + // Use linear clear color for gamma-correct rendering. + d3dCommandList->ClearRenderTargetView(m_deviceResources->GetHDR10RenderTargetView(), Black, 0, nullptr); + d3dCommandList->ClearRenderTargetView(m_deviceResources->GetGameDVRRenderTargetView(), Black, 0, nullptr); + d3dCommandList->ClearRenderTargetView(rtvDescriptor, Black, 0, nullptr); + d3dCommandList->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + d3dCommandList->RSSetViewports(1, &viewport); + d3dCommandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(d3dCommandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto d3dDevice = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(d3dDevice); + + m_fullScreenQuad = std::make_unique(); + m_fullScreenQuad->Initialize(d3dDevice); + + // Create descriptor heap for RTVs + m_rtvDescriptorHeap = std::make_unique(d3dDevice, + D3D12_DESCRIPTOR_HEAP_TYPE_RTV, + D3D12_DESCRIPTOR_HEAP_FLAG_NONE, + static_cast(RTVDescriptors::Count)); + + // Create descriptor heap for resources + m_resourceDescriptorHeap = std::make_unique(d3dDevice, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + static_cast(ResourceDescriptors::Count)); + + ResourceUploadBatch resourceUpload(d3dDevice); + resourceUpload.Begin(); + + // Create HDR backbuffer resources + auto outputSize = m_deviceResources->GetOutputSize(); + int width = outputSize.right - outputSize.left; + int height = outputSize.bottom - outputSize.top; + + m_hdrScene->SetDevice(d3dDevice, + m_resourceDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::HDRScene)), + m_rtvDescriptorHeap->GetCpuHandle(static_cast(RTVDescriptors::HDRScene))); + + m_hdrScene->SizeResources(width, height); + + // Init fonts + RenderTargetState rtState(m_hdrScene->GetFormat(), m_deviceResources->GetDepthBufferFormat()); + InitializeSpriteFonts(d3dDevice, resourceUpload, rtState); + + // SpriteBatch for rendering HDR values into the backbuffer + { + auto pixelShaderBlob = DX::ReadData(L"ColorPS.cso"); + SpriteBatchPipelineStateDescription pd(rtState); + pd.customPixelShader.BytecodeLength = pixelShaderBlob.size(); + pd.customPixelShader.pShaderBytecode = pixelShaderBlob.data(); + m_spriteBatch = std::make_unique(d3dDevice, resourceUpload, pd); + } + + // PrimitiveBatch for rendering lines into the backbuffer + { + D3D12_RASTERIZER_DESC state = CommonStates::CullNone; + state.MultisampleEnable = FALSE; + EffectPipelineStateDescription pd(&VertexPositionColor::InputLayout, CommonStates::Opaque, CommonStates::DepthDefault, state, rtState, D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE); + m_lineEffect = std::make_unique(d3dDevice, EffectFlags::VertexColor, pd); + m_primitiveBatch = std::make_unique>(d3dDevice); + } + + // PSO for rendering the HDR10 and GameDVR swapchain buffers + { + auto pixelShaderBlob = DX::ReadData(L"PrepareSwapChainBuffersPS.cso"); + auto vertexShaderBlob = DX::ReadData(L"FullScreenQuadVS.cso"); + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = m_fullScreenQuad->GetRootSignature(); + psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; + psoDesc.PS = { pixelShaderBlob.data(), pixelShaderBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 2; + psoDesc.RTVFormats[0] = m_deviceResources->GetHDR10BackBufferFormat(); + psoDesc.RTVFormats[1] = m_deviceResources->GetGameDVRFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed(d3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(m_d3dPrepareSwapChainBufferPSO.ReleaseAndGetAddressOf()))); + } + + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); // Wait for resources to upload +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} + +// Initialize all the fonts used +void Sample::InitializeSpriteFonts(ID3D12Device* d3dDevice, ResourceUploadBatch& resourceUpload, RenderTargetState& rtState) +{ + SpriteBatchPipelineStateDescription pd(rtState, &CommonStates::AlphaBlend); + m_fontBatch = std::make_unique(d3dDevice, resourceUpload, pd); + + auto cpuDescHandleText = m_resourceDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::TextFont)); + auto gpuDescHandleText = m_resourceDescriptorHeap->GetGpuHandle(static_cast(ResourceDescriptors::TextFont)); + m_textFont = std::make_unique(d3dDevice, resourceUpload, L"Courier_36.spritefont", cpuDescHandleText, gpuDescHandleText); + + auto cpuDescHandleController = m_resourceDescriptorHeap->GetCpuHandle(static_cast(ResourceDescriptors::ControllerFont)); + auto gpuDescHandleController = m_resourceDescriptorHeap->GetGpuHandle(static_cast(ResourceDescriptors::ControllerFont)); + m_controllerFont = std::make_unique(d3dDevice, resourceUpload, L"XboxOneControllerLegendSmall.spritefont", cpuDescHandleController, gpuDescHandleController); +} + +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.h b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.h new file mode 100644 index 0000000000000000000000000000000000000000..4c505b2ae9199266fcbfd5b827199590c6978029 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.h @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// SimpleHDR12.h +// +// This sample uses an API to determine if the attached display is HDR capable. If so, it +// will switch the display to HDR mode. A very simple HDR scene, with values above 1.0f, +// is rendered to a FP16 backbuffer and outputs to two different swapchains, one for HDR +// and one for SDR. Even if the consumer uses an HDR display, the SDR signal is still +// required for GameDVR and screenshots. +// +// Requirements for swapchain creation: +// 1) HDR swapchain has to be DXGI_FORMAT_R10G10B10A2_UNORM +// 2) HDR swapchain has to use XGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 +// +// See DeviceResources.cpp for swapchain creation and presentation +// +// Refer to the white paper “HDR on Xbox One” +// +// Up to now, games were outputting and SDR signal using Rec.709 color primaries and Rec.709 +// gamma curve. One new feature of UHD displays is a wider color gamut (WCG). To use this +// we need to use a new color space, Rec.2020 color primaries. Another new feature of UHD +// displays is high dynamic range (HDR). To use this we need to use a different curve, the +// ST.2084 curve. Therefore, to output an HDR signal, it needs to use Rec.2020 color primaries +// with ST.2084 curve. +// +// For displaying the SDR signal, a simple tonemapping shader is applied to simply clip all +// values above 1.0f in the HDR scene, and outputs 8bit values using Rec.709 color primaries, +// with the gamma curve applied. +// +// For displaying the HDR signal, a shader is used to rotate the Rec.709 color primaries to +// Rec.2020 color primaries, and then apply the ST.2084 curve to output 10bit values which +// the HDR display can correctly display. The whiteness and brightness of the output on an +// HDR display will be determined by the selected nits value for defining “paper white”. +// SDR specs define “paper white” as 80nits, but this is for a cinema with a dark environment. +// Consumers today are used to much brighter whites, e.g. ~550 nits for a smartphone(so that it +// can be viewed in sunlight), 200-300 nits for a PC monitor, 120-150 nits for an SDR TV, etc. +// The nits for “paper white” can be adjusted in the sample using the DPad up/down. Displaying +// bright values next to white can be deceiving to the eye, so you can use the A button to +// toggle if you only want to see the “paper white” block. +// +// The sample has two modes: +// 1) Render blocks with specific values in the scene +// 2) Render ST.2084 curve with specific brightness values(nits) +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "FullScreenQuad.h" +#include "RenderTexture.h" + +// A basic sample implementation that creates a D3D12 device and provides a render loop. +class Sample +{ +#pragma region Standard Sample Defines +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + void Init(IUnknown* window); + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + void InitializeSpriteFonts(ID3D12Device* d3dDevice, DirectX::ResourceUploadBatch& resourceUpload, DirectX::RenderTargetState& rtState); + + // Standard sample defines + std::unique_ptr m_deviceResources; + uint64_t m_frame; + DX::StepTimer m_timer; + std::unique_ptr m_gamePad; + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_rtvDescriptorHeap; + std::unique_ptr m_resourceDescriptorHeap; + std::unique_ptr m_textFont; + std::unique_ptr m_controllerFont; + std::unique_ptr m_fontBatch; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_states; + std::unique_ptr m_lineEffect; + Microsoft::WRL::ComPtr m_inputLayout; + std::unique_ptr> m_primitiveBatch; + std::unique_ptr m_fullScreenQuad; + +#pragma endregion + +#pragma region HDR Defines + + std::atomic_bool m_bIsTVInHDRMode; // This will be set to TRUE if the attached display is in HDR mode + bool m_bRender2084Curve; // Render the ST.2084 curve rather than the HDR scene + bool m_bShowOnlyPaperWhite; // If enabled, only the block with value 1.0f (paper white) will be rendered. Seeing bright values next to white can have the effect of perceiving white as gray + double m_countDownToBright; // The countdown before rendering bright values at the start of the sample, so that eyes can adjust to what paper white looks like, to realize the difference between white and bright + float m_current2084CurveRenderingNits; // In the mode when rendering the curve, use this as the adjustable value indicated on the graph + const int g_CustomInputValueIndex = 3; // Index of input values set by left/right sticks, others use fixed values + static const int NUM_INPUT_VALUES = 4; + float m_hdrSceneValues[NUM_INPUT_VALUES] = { 0.5f, 1.0f, 6.0f, 10.0f }; // Values that will be rendering to the HDR scene buffer + std::unique_ptr m_hdrScene; + + struct HDR10Data + { + float PaperWhiteNits; // Defines how bright white is (in nits), which controls how bright the SDR range in the image will be, e.g. 200 nits + } m_HDR10Data; + + void RenderHDRScene(); + void Render2084Curve(); + void RenderUI(); + void PrepareSwapChainBuffers(); // Takes as input the HDR scene values and outputs an HDR and SDR signal to two seperate swapchains + + inline DirectX::XMVECTOR MakeColor(float value) { DirectX::XMVECTORF32 color = { value, value, value, 1.0f }; return color; } + +#pragma endregion + +#pragma region D3D12 Defines + + Microsoft::WRL::ComPtr m_d3dRootSignature; + Microsoft::WRL::ComPtr m_d3dRenderHDRScenePSO; + Microsoft::WRL::ComPtr m_d3dPrepareSwapChainBufferPSO; + + // Descriptors for m_rtvDescriptorHeap + enum class RTVDescriptors + { + HDRScene, + Count + }; + + // Desriptors for m_resourceDescriptorHeap + enum class ResourceDescriptors + { + HDRScene, + TextFont, + ControllerFont, + Count + }; + +#pragma endregion + +}; diff --git a/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.sln b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.sln new file mode 100644 index 0000000000000000000000000000000000000000..0d02d34fbccc77d6ebe422f238206a609da19f0f --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleHDR12", "SimpleHDR12.vcxproj", "{54296DA6-82DF-4BA2-8D28-4A235F3AFC92}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Debug|Durango.ActiveCfg = Debug|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Debug|Durango.Build.0 = Debug|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Debug|Durango.Deploy.0 = Debug|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Profile|Durango.ActiveCfg = Profile|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Profile|Durango.Build.0 = Profile|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Profile|Durango.Deploy.0 = Profile|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Release|Durango.ActiveCfg = Release|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Release|Durango.Build.0 = Release|Durango + {54296DA6-82DF-4BA2-8D28-4A235F3AFC92}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.vcxproj b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..803c554b2d23637a881df2780badb523a30c0aca --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.vcxproj @@ -0,0 +1,257 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleHDR12 + {54296da6-82df-4ba2-8d28-4a235f3afc92} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\ATGTK\HDR;..\..\..\Kits\ATGTK\FullScreenQuad;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + ..\..\..\Kits\DirectXTK12\Src\Shaders;..\..\..\Kits\ATGTK\HDR;..\..\..\Kits\ATGTK\FullScreenQuad + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\ATGTK\HDR;..\..\..\Kits\ATGTK\FullScreenQuad;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + ..\..\..\Kits\DirectXTK12\Src\Shaders;..\..\..\Kits\ATGTK\HDR;..\..\..\Kits\ATGTK\FullScreenQuad + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\ATGTK\HDR;..\..\..\Kits\ATGTK\FullScreenQuad;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + ..\..\..\Kits\DirectXTK12\Src\Shaders;..\..\..\Kits\ATGTK\HDR;..\..\..\Kits\ATGTK\FullScreenQuad + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + Designer + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + + + + + + + + + true + true + true + + + true + true + true + + + + + + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + + + main + Pixel + main + Pixel + main + Pixel + + + Pixel + Pixel + Pixel + + + + + + \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.vcxproj.filters b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..1a20bec450f305f28985d0257e5b9d93dfb737f0 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/SimpleHDR12.vcxproj.filters @@ -0,0 +1,133 @@ + + + + + {0b40f5a9-d597-4f04-a005-917adae14bfc} + + + {72f10675-2957-4e8d-9225-6fb17a566f9b} + + + a1988fec-9787-4d39-ab6c-9896d71b8c07 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 5aa7490a-2980-4ed3-b75c-54b6b88740ab + + + 95758d61-af0e-4b0f-a463-14c1ebe277a7 + + + {faace108-b541-435e-8036-147341bce546} + + + {0fbf4752-a7d3-4b8e-86a9-c715dab31768} + + + + + Standard Sample Files\Common + + + Standard Sample Files\Common + + + Standard Sample Files + + + HDR + + + HDR + + + Standard Sample Files\ATG Tool Kit + + + Standard Sample Files\ATG Tool Kit + + + Standard Sample Files\ATG Tool Kit + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + Standard Sample Files\ATG Tool Kit + + + + + Standard Sample Files + + + Standard Sample Files + + + HDR + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + Standard Sample Files\ATG Tool Kit + + + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + + + Standard Sample Files + + + + + + Standard Sample Files\Assets + + + Standard Sample Files\Assets + + + HDR + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + + + HDR + + + Standard Sample Files\Shaders + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + Standard Sample Files\ATG Tool Kit\FullScreenQuad + + + \ No newline at end of file diff --git a/XDKSamples/Graphics/SimpleHDR12/StepTimer.h b/XDKSamples/Graphics/SimpleHDR12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Graphics/SimpleHDR12/Telemetry.h b/XDKSamples/Graphics/SimpleHDR12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Graphics/SimpleHDR12/pch.cpp b/XDKSamples/Graphics/SimpleHDR12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Graphics/SimpleHDR12/pch.h b/XDKSamples/Graphics/SimpleHDR12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..213c10056b08461a40664c8caa2858b65af22f3c --- /dev/null +++ b/XDKSamples/Graphics/SimpleHDR12/pch.h @@ -0,0 +1,74 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "CommonStates.h" +#include "DescriptorHeap.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "PrimitiveBatch.h" +#include "RenderTargetState.h" +#include "ResourceUploadBatch.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "VertexTypes.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/LogoXDK.png b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/LogoXDK.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/LogoXDK.png differ diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/SmallLogoXDK.png b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/SmallLogoXDK.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/SmallLogoXDK.png differ diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/SplashScreenXDK.png b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/SplashScreenXDK.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/SplashScreenXDK.png differ diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/StoreLogoXDK.png b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/StoreLogoXDK.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/StoreLogoXDK.png differ diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/WideLogoXDK.png b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/WideLogoXDK.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/Graphics/SimplePBR12_Xbox/Assets/WideLogoXDK.png differ diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Readme.docx b/XDKSamples/Graphics/SimplePBR12_Xbox/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..b4005e42c9fd254954c1aef0eb217918e33fda65 Binary files /dev/null and b/XDKSamples/Graphics/SimplePBR12_Xbox/Readme.docx differ diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/PBRModel.h b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/PBRModel.h new file mode 100644 index 0000000000000000000000000000000000000000..fe5d3ed1b12e1a4f7065a8846f01985748f46bf4 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/PBRModel.h @@ -0,0 +1,121 @@ +//-------------------------------------------------------------------------------------- +// PBRModel.h +// +// A wrapper for SDKMesh models that use PBR materials. +// +// This implies the follwing folder structure and naming convention for source assets: +// +// modelPath\modelName.sdkmesh +// modelPath\materalName\modelname_BaseColor.png +// modelPath\materalName\modelname_Normal.png +// modelPath\materalName\modelname_Roughness.png +// modelPath\materalName\modelname_Metallic.png +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include "PBREffect\PBREffect.h" + +namespace ATG +{ + class PBRModel + { + public: + PBRModel(const wchar_t* modelPath) + : m_modelFullPath(modelPath) + { + // Remove extension and path + auto lastSlash = m_modelFullPath.find_last_of(L"\\"); + if (lastSlash != size_t(-1)) + m_modelBasePath = m_modelFullPath.substr(0, lastSlash); + else + m_modelBasePath = L"."; + + auto lastDot = m_modelFullPath.find_last_of(L"."); + m_modelName = m_modelFullPath.substr( lastSlash + 1, lastDot - lastSlash - 1); + } + + void Create( + _In_ ID3D12Device* device, + const DirectX::RenderTargetState& rtState, + const DirectX::CommonStates* commonStates, + DirectX::ResourceUploadBatch& resourceUpload, + _In_ DirectX::DescriptorPile* pile) + { + using namespace DirectX; + using namespace DirectX::SimpleMath; + + // Generate paths for resources + enum Textures + { + Albedo = 0, + Normal, + RMA, + MaxTextures + }; + + wchar_t fullTexturePath[MaxTextures][_MAX_PATH] = {}; + + swprintf_s(fullTexturePath[Albedo], L"%s\\%s_BaseColor.dds", m_modelBasePath.c_str(), m_modelName.c_str()); + swprintf_s(fullTexturePath[Normal], L"%s\\%s_Normal.dds", m_modelBasePath.c_str(), m_modelName.c_str()); + swprintf_s(fullTexturePath[RMA], L"%s\\%s_RMA.dds", m_modelBasePath.c_str(), m_modelName.c_str()); + + // PBR Model + m_model = Model::CreateFromSDKMESH(m_modelFullPath.c_str()); + + // PBR Textures + // Force SRGB on albedo texture + DX::ThrowIfFailed( + CreateDDSTextureFromFileEx(device, resourceUpload, fullTexturePath[Albedo], 0, + D3D12_RESOURCE_FLAG_NONE, WIC_LOADER_FORCE_SRGB, + m_textureResources[Albedo].ReleaseAndGetAddressOf())); + + // Reload others as linear + for (size_t i = Normal; i < MaxTextures; i++) + { + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, resourceUpload, fullTexturePath[i], + m_textureResources[i].ReleaseAndGetAddressOf())); + } + + // Allocate a range of descriptors from pile + DescriptorPile::IndexType start, end; + pile->AllocateRange(MaxTextures, start, end); + + for (size_t i = 0; i < MaxTextures; i++) + { + CreateShaderResourceView(device, m_textureResources[i].Get(), pile->GetCpuHandle(start + i)); + } + + // Create PBR Effect + EffectPipelineStateDescription pbrEffectPipelineState( + &ATG::VertexPositionNormalTextureTangent::InputLayout, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState, + D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE); + m_effect = std::make_unique(device, EffectFlags::Texture, pbrEffectPipelineState); + + // Set surface textures + m_effect->SetSurfaceTextures(pile->GetGpuHandle(start + Albedo), + pile->GetGpuHandle(start + Normal), + pile->GetGpuHandle(start + RMA), + commonStates->AnisotropicClamp()); + } + + const DirectX::Model* GetModel() const { return m_model.get(); } + ATG::PBREffect* GetEffect() const { return m_effect.get(); } + + private: + std::wstring m_modelFullPath; + std::wstring m_modelBasePath; + std::wstring m_modelName; + + std::unique_ptr m_model; + std::unique_ptr m_effect; + Microsoft::WRL::ComPtr m_textureResources[4]; + }; +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/SharedSimplePBR.cpp b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/SharedSimplePBR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d0c1030c28129ea946f2b2c9c8f1cfaa8c040d5 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/SharedSimplePBR.cpp @@ -0,0 +1,433 @@ +//-------------------------------------------------------------------------------------- +// SharedSimplePBR.h +// +// Shared sample class to demonstrate PBRModel and PBREffect in DirectX 12 on Xbox ERA +// and PC UWP. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SharedSimplePBR.h" + +#include "ControllerFont.h" +#include "DDSTextureLoader.h" +#include "GeometricPrimitive.h" + +//#define TEST_SCENE + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include "../Xbox/SimplePBRXbox12.h" // get sample definition +#else +#include "../UWP/SimplePBRUWP12.h" // get sample definition +#endif + + +using namespace DirectX; +using namespace DirectX::SimpleMath; +using Microsoft::WRL::ComPtr; + +namespace +{ + // PBR Assest paths. + const wchar_t* s_modelPaths[] = + { + L"Floor.sdkmesh", + L"ToyRobot.sdkmesh", + L"WoodBlocks.sdkmesh" + }; + + // A simple test scene for material parameters + struct TestScene + { + std::unique_ptr m_model; + std::unique_ptr m_sphere; + std::unique_ptr m_effect; + + void Init(ID3D12Device* device, + D3D12_GPU_DESCRIPTOR_HANDLE radianceTex, int numMips, + D3D12_GPU_DESCRIPTOR_HANDLE irradianceTex, + D3D12_GPU_DESCRIPTOR_HANDLE sampler) + { + RenderTargetState hdrBufferRts(Sample::GetHDRRenderFormat(), Sample::GetDepthFormat()); + + m_sphere = DirectX::GeometricPrimitive::CreateSphere(1.5); + + // Create PBR Effect + EffectPipelineStateDescription pbrEffectPipelineState( + &ATG::VertexPositionNormalTextureTangent::InputLayout, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + hdrBufferRts, + D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE); + m_effect = std::make_unique(device, EffectFlags::None, pbrEffectPipelineState); + + // Lighting + m_effect->SetIBLTextures( + radianceTex, + numMips, + irradianceTex, + sampler); + + // Model + m_model = Model::CreateFromSDKMESH(L"XboxOrb.sdkmesh"); + } + + void XM_CALLCONV Render(ID3D12GraphicsCommandList* commandList, FXMMATRIX camView, CXMMATRIX camProj) + { + const size_t numSpheres = 3; + const float step = 15.f; + + Vector3 modelPos((-step * (numSpheres- 1)) / 2.f, 0, 0); + + m_effect->SetConstantAlbedo(Vector3(1, 1, 1)); + m_effect->SetConstantMetallic(1); + + for (size_t i = 0; i < numSpheres; i++) + { + m_effect->SetView(camView); + m_effect->SetProjection(camProj); + m_effect->SetWorld(Matrix::CreateTranslation(modelPos)); + + modelPos += Vector3(step, 0, 0); + + m_effect->SetConstantRoughness(float(i) / float(numSpheres-1)); + + m_effect->Apply(commandList); + m_model->DrawOpaque(commandList); + } + + modelPos = Vector3((-step * (numSpheres - 1)) / 2.f, 0, 0); + modelPos += Vector3(0, step, 0); + + m_effect->SetConstantMetallic(0); + + for (size_t i = 0; i < numSpheres; i++) + { + m_effect->SetView(camView); + m_effect->SetProjection(camProj); + m_effect->SetWorld(Matrix::CreateTranslation(modelPos)); + + modelPos += Vector3(step, 0, 0); + + m_effect->SetConstantRoughness(float(i) / float(numSpheres-1)); + + m_effect->Apply(commandList); + m_model->DrawOpaque(commandList); + } + } + }; + + std::unique_ptr s_testScene; +} + +SharedSimplePBR::SharedSimplePBR(Sample* sample) : + m_sample(sample), + m_gamepadConnected(false) +{ + m_gamePad = std::make_unique(); + + m_hdrScene = std::make_unique(Sample::GetHDRRenderFormat()); +} + +void SharedSimplePBR::Update(DX::StepTimer const& timer) +{ + const float elapsedSeconds = static_cast(timer.GetElapsedSeconds()); + + // Update camera via game pad + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamepadConnected = true; + + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamepadConnected = false; + + m_gamePadButtons.Reset(); + } + m_camera->Update(elapsedSeconds, pad); + +#if !defined(_XBOX_ONE) || !defined(_TITLE) + // KB/Mouse currently only PC + m_camera->Update(elapsedSeconds, *(m_sample->m_mouse.get()), *(m_sample->m_keyboard.get())); +#endif + + // Update model effects + for (auto& m : m_pbrModels) + { + auto effect = m->GetEffect(); + effect->SetView(m_camera->GetView()); + effect->SetProjection(m_camera->GetProjection()); + effect->SetWorld(Matrix::CreateRotationY(XM_PI)); + } + + // Update skybox + m_skybox->Update(m_camera->GetView(), m_camera->GetProjection()); +} + +void SharedSimplePBR::Render() +{ + // Resources and dimensions for this render + DX::DeviceResources* deviceResources = m_sample->m_deviceResources.get(); + auto commandList = deviceResources->GetCommandList(); + auto size = deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + // Set descriptor heaps + ID3D12DescriptorHeap* heaps[] = { m_srvPile->Heap(), m_commonStates->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Draw to HDR buffer + m_hdrScene->BeginScene(commandList); + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render HDR"); + + auto depthStencilDescriptor = deviceResources->GetDepthStencilView(); + auto toneMapRTVDescriptor = m_rtvHeap->GetFirstCpuHandle(); + commandList->OMSetRenderTargets(1, &toneMapRTVDescriptor, FALSE, &depthStencilDescriptor); + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Model Draw"); +#ifndef TEST_SCENE + for (auto& m : m_pbrModels) + { + m->GetEffect()->Apply(commandList); + m->GetModel()->DrawOpaque(commandList); + } +#else + s_testScene->Render(commandList, m_camera->GetView(), m_camera->GetProjection()); +#endif + PIXEndEvent(commandList); // Model Draw + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Sky box"); + { + // Render test skybox + m_skybox->Render(commandList); + } + + PIXEndEvent(commandList); + + PIXEndEvent(commandList); // Render HDR + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Tonemap HDR to SDR backbuffer"); + { + auto rtv = static_cast(deviceResources->GetRenderTargetView()); + commandList->OMSetRenderTargets(1, &rtv, FALSE, NULL); + + m_hdrScene->EndScene(commandList); + + // Tonemap + m_toneMap->SetHDRSourceTexture(m_srvPile->GetGpuHandle(StaticDescriptors::SceneTex)); + m_toneMap->Process(commandList); + } + PIXEndEvent(commandList); // Tonemap + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render HUD"); + { + m_hudBatch->Begin(commandList); + + m_smallFont->DrawString(m_hudBatch.get(), L"SimplePBR Sample", + XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::LightGrey); + + const wchar_t* legendStr = (m_gamepadConnected) ? + L"[RThumb] [LThumb]: Move Camera [View] Exit " + : L"Mouse, W,A,S,D: Move Camera Esc: Exit "; + + DX::DrawControllerString(m_hudBatch.get(), + m_smallFont.get(), m_ctrlFont.get(), + legendStr, + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_hudBatch->End(); + } + PIXEndEvent(commandList); // HUD + + PIXEndEvent(commandList); // Render +} + +void SharedSimplePBR::CreateDeviceDependentResources() +{ + auto device = m_sample->m_deviceResources->GetD3DDevice(); + + // State objects + m_commonStates = std::make_unique(device); + + // create heaps + m_srvPile = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + 128, // Maximum descriptors for both static and dynamic + StaticDescriptors::Reserve); + m_rtvHeap = std::make_unique(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1); + + // Set up HDR render target. + m_hdrScene->SetDevice(device, m_srvPile->GetCpuHandle(StaticDescriptors::SceneTex), m_rtvHeap->GetFirstCpuHandle()); + + // Begin uploading texture resources + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); + + // Radiance (specular environment) texture + DX::ThrowIfFailed( + DirectX::CreateDDSTextureFromFile( + device, + resourceUpload, + L"Stonewall_Ref_radiance.dds", + m_radianceTexture.ReleaseAndGetAddressOf(), + false + )); + + DirectX::CreateShaderResourceView(device, m_radianceTexture.Get(), m_srvPile->GetCpuHandle(StaticDescriptors::RadianceTex), true); + + // Irradiance (diffuse environment) texture + DX::ThrowIfFailed( + DirectX::CreateDDSTextureFromFile( + device, + resourceUpload, + L"Stonewall_Ref_irradiance.dds", + m_irradianceTexture.ReleaseAndGetAddressOf(), + false + )); + + DirectX::CreateShaderResourceView(device, m_irradianceTexture.Get(), m_srvPile->GetCpuHandle(StaticDescriptors::IrradianceTex), true); + + // Pipeline state - for rendering direct to back buffer + { + RenderTargetState backBufferRts(Sample::GetBackBufferFormat(), Sample::GetDepthFormat()); + + // HUD + DirectX::SpriteBatchPipelineStateDescription hudpd( + backBufferRts, + &CommonStates::AlphaBlend); + + m_hudBatch = std::make_unique(device, resourceUpload, hudpd); + + // Create tone mapping effect + m_toneMap = std::make_unique(device, backBufferRts, + ToneMapPostProcess::ACESFilmic, ToneMapPostProcess::SRGB); + } + + // Pipeline state - for rendering to HDR buffer + { + RenderTargetState hdrBufferRts(Sample::GetHDRRenderFormat(), Sample::GetDepthFormat()); + + // Sky rendering batch + m_spriteBatch = std::make_unique(device, resourceUpload, SpriteBatchPipelineStateDescription(hdrBufferRts, &CommonStates::Opaque)); + + // PBR Model + const auto numModels = _countof(s_modelPaths); + m_pbrModels.resize(numModels); + + for (auto i = 0; i < numModels; i++) + { + m_pbrModels[i] = std::make_unique(s_modelPaths[i]); + m_pbrModels[i]->Create(device, hdrBufferRts, m_commonStates.get(), resourceUpload, m_srvPile.get()); + } + + // Skybox + m_skybox = std::make_unique(device, m_srvPile->GetGpuHandle(StaticDescriptors::RadianceTex), hdrBufferRts, *m_commonStates); + } + + // The current map has too much detail removed at last mips, scale back down to + // match reference. + const int numMips = m_radianceTexture->GetDesc().MipLevels - 3; + + // Set lighting textures for each model + for (auto& m : m_pbrModels) + { + m->GetEffect()->SetIBLTextures( + m_srvPile->GetGpuHandle(StaticDescriptors::RadianceTex), + numMips, + m_srvPile->GetGpuHandle(StaticDescriptors::IrradianceTex), + m_commonStates->LinearWrap()); + } + + s_testScene = std::make_unique(); + s_testScene->Init(device, m_srvPile->GetGpuHandle(StaticDescriptors::RadianceTex), + numMips, + m_srvPile->GetGpuHandle(StaticDescriptors::IrradianceTex), + m_commonStates->LinearWrap()); + + auto finished = resourceUpload.End(m_sample->m_deviceResources->GetCommandQueue()); + finished.wait(); +} + +void SharedSimplePBR::CreateWindowSizeDependentResources() +{ + auto device = m_sample->m_deviceResources->GetD3DDevice(); + const auto size = m_sample->m_deviceResources->GetOutputSize(); + + // Set hud sprite viewport + m_hudBatch->SetViewport(m_sample->m_deviceResources->GetScreenViewport()); + + // set camera + { + const float fovAngleY = 70.0f * XM_PI / 180.0f; + + m_camera = std::make_unique(); + m_camera->SetWindow(size.right, size.bottom); + m_camera->SetProjectionParameters(fovAngleY, 0.1f, 1000.f, false); + m_camera->SetRadius(25.f); + m_camera->SetRadiusRate(5.f); + m_camera->SetFocus(Vector3(0, 4, -5)); + // Rotate to face front + m_camera->SetRotation(Vector3(0, XM_PI, XM_PI / 10)); + } + + // HDR render target resource + m_hdrScene->SetWindow(size); + + // Begin uploading texture resources + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); + + m_smallFont = std::make_unique(device, resourceUpload, + (size.bottom > 1200) ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont", + m_srvPile->GetCpuHandle(StaticDescriptors::Font), + m_srvPile->GetGpuHandle(StaticDescriptors::Font)); + + m_ctrlFont = std::make_unique(device, resourceUpload, + (size.bottom > 1200) ? L"XboxOneControllerLegend.spritefont" : L"XboxOneControllerLegendSmall.spritefont", + m_srvPile->GetCpuHandle(StaticDescriptors::CtrlFont), + m_srvPile->GetGpuHandle(StaticDescriptors::CtrlFont)); + + auto finished = resourceUpload.End(m_sample->m_deviceResources->GetCommandQueue()); + finished.wait(); +} + +// For UWP only +void SharedSimplePBR::OnDeviceLost() +{ + m_hudBatch.reset(); + m_smallFont.reset(); + m_ctrlFont.reset(); + + m_camera.reset(); + m_commonStates.reset(); + + m_srvPile.reset(); + + m_spriteBatch.reset(); + m_toneMap.reset(); + + m_hdrScene->ReleaseDevice(); + m_rtvHeap.reset(); + + for (auto& m : m_pbrModels) + { + m.reset(); + } +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/SharedSimplePBR.h b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/SharedSimplePBR.h new file mode 100644 index 0000000000000000000000000000000000000000..d09e36cd8a55dfffebad36b6419818bc8a512f3b --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/SharedSimplePBR.h @@ -0,0 +1,86 @@ +//-------------------------------------------------------------------------------------- +// SharedSimplePBR.h +// +// Shared sample class to demonstrate PBRModel and PBREffect in DirectX 12 on Xbox ERA +// and PC UWP. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "StepTimer.h" + +#include "PBREffect/PBREffect.h" +#include "Skybox/Skybox.h" +#include "GeometricPrimitive.h" +#include "PBRModel.h" +#include "RenderTexture.h" + +class Sample; + +class SharedSimplePBR +{ +public: + SharedSimplePBR(Sample* sample); + ~SharedSimplePBR() {} + + void Update(DX::StepTimer const& timer); + void Render(); + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + void OnDeviceLost(); + +private: + Sample* m_sample; + + // Hud + std::unique_ptr m_hudBatch; + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + // Input and Camera + std::unique_ptr m_gamePad; + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + std::unique_ptr m_camera; + bool m_gamepadConnected; + + // Render states + std::unique_ptr m_commonStates; + + // All SRV descriptors for sample + std::unique_ptr m_srvPile; + + enum StaticDescriptors + { + Font, + CtrlFont, + SceneTex, + RadianceTex, + IrradianceTex, + Reserve + }; + + // Drawing + using DebugVert = DirectX::VertexPositionColor; + + std::unique_ptr m_spriteBatch; + std::unique_ptr m_toneMap; + + // Render target view for tonemapping + std::unique_ptr m_hdrScene; + std::unique_ptr m_rtvHeap; + + // Sky/Environment textures + Microsoft::WRL::ComPtr m_radianceTexture; + + // Irradiance texture + Microsoft::WRL::ComPtr m_irradianceTexture; + + // Model + std::vector< std::unique_ptr> m_pbrModels; + + // Skybox + std::unique_ptr m_skybox; +}; \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/StepTimer.h b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Shared/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.sln b/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.sln new file mode 100644 index 0000000000000000000000000000000000000000..9c02b0d0a7a48a100da0ca960c6873410d4b2d38 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimplePBRXbox12", "SimplePBRXbox12.vcxproj", "{7A221FD3-BEC4-4652-91F0-AD061D80E200}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Debug|Durango.ActiveCfg = Debug|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Debug|Durango.Build.0 = Debug|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Debug|Durango.Deploy.0 = Debug|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Profile|Durango.ActiveCfg = Profile|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Profile|Durango.Build.0 = Profile|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Profile|Durango.Deploy.0 = Profile|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Release|Durango.ActiveCfg = Release|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Release|Durango.Build.0 = Release|Durango + {7A221FD3-BEC4-4652-91F0-AD061D80E200}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.vcxproj b/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..37f6da24a0d24f12fe7cb7304ba0fca49f094711 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.vcxproj @@ -0,0 +1,381 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimplePBRXbox + {7a221fd3-bec4-4652-91f0-ad061d80e200} + en-US + Win32Proj + title + + v140 + 14.0 + Native + SimplePBRXbox12 + 8.1 + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + $(SolutionDir)$(Platform)\$(Configuration)\$(MSBuildProjectName)\ + $(Platform)\$(Configuration)\ + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + $(SolutionDir)$(Platform)\$(Configuration)\$(MSBuildProjectName)\ + $(Platform)\$(Configuration)\ + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + $(SolutionDir)$(Platform)\$(Configuration)\$(MSBuildProjectName)\ + $(Platform)\$(Configuration)\ + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + $(ProjectDir);$(ProjectDir)..\..\..\Kits\DirectXTK12\Inc;$(ProjectDir)..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + $(ProjectDir);$(ProjectDir)..\..\..\Kits\DirectXTK12\Inc;$(ProjectDir)..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + $(ProjectDir);$(ProjectDir)..\..\..\Kits\DirectXTK12\Inc;$(ProjectDir)..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + + + + Create + Create + Create + + + + + + + + + Designer + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + Pixel + Pixel + Pixel + PSConstant + PSConstant + PSConstant + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + PSTextured + Pixel + PSTextured + Pixel + PSTextured + Pixel + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + VSConstant + Vertex + VSConstant + Vertex + VSConstant + Vertex + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + Pixel + Pixel + Pixel + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + %(Filename) + %(ProjectDir)Compiled\XboxOne%(Filename).inc + + + Vertex + Vertex + Vertex + + + + + + \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.vcxproj.filters b/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..ae9aeee8d5fc856196ecae02167b9306a6d79729 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/SimplePBRXbox12.vcxproj.filters @@ -0,0 +1,232 @@ + + + + + ad58fb87-f5eb-4163-a0dd-a5bfafe493e7 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {002326c2-4322-4c2f-97b1-cbc9e2044cb5} + + + {32b1819f-374a-47a1-829b-a30775decd8a} + + + 9d910f65-6fd5-4843-88f8-9969c25d6df7 + + + {9c7649a9-9376-457c-8e43-ef4c89b37d2f} + + + {43d1bff7-9b79-4f45-aed0-48d3499a2775} + + + {432b853d-d569-49d2-918d-77b626bc65a0} + + + {e6abdfe7-dfd4-4d1e-be5d-9ea4f8fc8ffc} + + + {c352b6a0-950b-46fe-8fe4-32af4b4693b9} + + + {a740d124-8b61-4830-a28b-5ea1f908a7aa} + + + {6b8a0f67-55d0-418e-8a14-d91187291f87} + + + {66fe32ec-4c55-422d-b81c-8c68e771e14c} + + + {7f6359a3-e687-4025-96e6-3e3deb44ad97} + + + {85e9fac7-27b3-4f90-8194-aaffd1045b79} + + + {7dfae8d3-923a-4fa3-99a0-926e661567d0} + + + + + Xbox + + + Xbox + + + Shared + + + Shared + + + Shared + + + ATG Tool Kit + + + Xbox + + + Shared + + + ATG Tool Kit + + + ATG Tool Kit\PBREffect + + + Shared + + + ATG Tool Kit\Skybox + + + ATG Tool Kit\Skybox + + + ATG Tool Kit + + + + + Assets\Logo + + + Assets\Logo + + + Assets\Logo + + + Assets\Logo + + + Assets\Logo + + + Assets\Models\ToyRobot\WoodBlocks + + + Assets\Models\ToyRobot\ToyRobot + + + Assets\Models\ToyRobot\Floor + + + Assets\Backgrounds + + + Assets\Backgrounds + + + Assets\Models\ToyRobot\Floor + + + Assets\Models\ToyRobot\Floor + + + Assets\Models\ToyRobot\ToyRobot + + + Assets\Models\ToyRobot\ToyRobot + + + Assets\Models\ToyRobot\WoodBlocks + + + Assets\Models\ToyRobot\WoodBlocks + + + + + Xbox + + + Xbox + + + Shared + + + Shared + + + ATG Tool Kit + + + Xbox + + + ATG Tool Kit\PBREffect + + + ATG Tool Kit\Skybox + + + ATG Tool Kit + + + + + Xbox + + + + + Assets\Models\XboxOrb + + + + ATG Tool Kit\PBREffect + + + ATG Tool Kit\PBREffect + + + Assets\Models\ToyRobot\WoodBlocks + + + Assets\Models\ToyRobot\ToyRobot + + + Assets\Models\ToyRobot\Floor + + + ATG Tool Kit\Skybox + + + Assets\Fonts + + + Assets\Fonts + + + Assets\Fonts + + + Assets\Fonts + + + + + ATG Tool Kit\PBREffect + + + ATG Tool Kit\PBREffect + + + ATG Tool Kit\PBREffect + + + ATG Tool Kit\Skybox + + + ATG Tool Kit\Skybox + + + \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/DeviceResources.cpp b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0044ff37c22d155694d122ff3d12478d5328016 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/DeviceResources.cpp @@ -0,0 +1,459 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_renderTargetsGameDVR[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); + + swprintf_s(name, L"GameDVR Render target %u", n); + m_renderTargetsGameDVR[n]->SetName(name); + + rtvDesc.Format = m_gameDVRFormat; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferCount + n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); + } + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + if (m_options & c_EnableHDR) + { + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET), + }; + m_commandList->ResourceBarrier(_countof(barriers), barriers); + } + else + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + if (m_options & c_EnableHDR) + { + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), + }; + m_commandList->ResourceBarrier(_countof(barriers), barriers); + } + else + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/DeviceResources.h b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4233f622b36ee0a25f19008392290195813eb63 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/DeviceResources.h @@ -0,0 +1,116 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + static const unsigned int c_EnableHDR = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D12Resource* GetGameDVRRenderTarget() const { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferCount + m_backBufferIndex, m_rtvDescriptorSize); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; + DXGI_FORMAT m_gameDVRFormat; + }; +} diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Main.cpp b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f93271e8697f161b53401f6217244328f9142f0 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Main.cpp @@ -0,0 +1,153 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimplePBRXbox12.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Package.appxmanifest b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..13740ca2fe4cb19f53c583f444700b84ee99f4aa --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimplePBRXbox + Xbox Advanced Technology Group + Assets\StoreLogoXDK.png + SimplePBRXbox + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/SimplePBRXbox12.cpp b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/SimplePBRXbox12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf1aac48bb59cfe601c92769eeede27e06cb67f3 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/SimplePBRXbox12.cpp @@ -0,0 +1,142 @@ +//-------------------------------------------------------------------------------------- +// SimplePBRXbox.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimplePBRXbox12.h" + +#include "ATGColors.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(GetBackBufferFormat(), GetDepthFormat(), 2, DX::DeviceResources::c_Enable4K_UHD); + m_sharedSimplePBR = std::make_unique(this); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + m_sharedSimplePBR->Update(timer); + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + m_sharedSimplePBR->Render(); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device); + + m_sharedSimplePBR->CreateDeviceDependentResources(); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + m_sharedSimplePBR->CreateWindowSizeDependentResources(); +} +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/SimplePBRXbox12.h b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/SimplePBRXbox12.h new file mode 100644 index 0000000000000000000000000000000000000000..f3ba5a530f930824ef484a89b19a918539fef61c --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/SimplePBRXbox12.h @@ -0,0 +1,59 @@ +//-------------------------------------------------------------------------------------- +// SimplePBRXbox.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "..\Shared\StepTimer.h" +#include "..\Shared\SharedSimplePBR.h" + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + friend class SharedSimplePBR; + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + + inline static DXGI_FORMAT GetHDRRenderFormat() { return DXGI_FORMAT_R11G11B10_FLOAT; } + inline static DXGI_FORMAT GetBackBufferFormat() { return DXGI_FORMAT_R10G10B10A2_UNORM; } + inline static DXGI_FORMAT GetDepthFormat() { return DXGI_FORMAT_D32_FLOAT; } + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Core shared sample object + std::unique_ptr m_sharedSimplePBR; +}; diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Telemetry.h b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/Xbox/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/pch.cpp b/XDKSamples/Graphics/SimplePBR12_Xbox/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..373fab978849f3a706f121ec463bccd4d5d35837 --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Graphics/SimplePBR12_Xbox/pch.h b/XDKSamples/Graphics/SimplePBR12_Xbox/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..e5c9a172634115fe97d5e81cd475dc6772a1fbbd --- /dev/null +++ b/XDKSamples/Graphics/SimplePBR12_Xbox/pch.h @@ -0,0 +1,99 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if defined(_XBOX_ONE) && defined(_TITLE) + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include + +#else + +#include +#include "d3dx12.h" +#include + +#ifdef _DEBUG +#include +#endif + +#endif + +#include +#include + + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/Logo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/WideLogo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/seafloor.dds b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/seafloor.dds new file mode 100644 index 0000000000000000000000000000000000000000..02db0a0c4b947d29c3a6bf9eeb61ce2a3c27d2ee Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/seafloor.dds differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/windowslogo.dds b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/windowslogo.dds new file mode 100644 index 0000000000000000000000000000000000000000..38f6dc861d598dfb51bdea5ed1a62234cf77a600 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Assets/windowslogo.dds differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DeviceResources.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DeviceResources.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ea4e4276a63cb07be028fd58ae1dfb3a10ac84c --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.cpp @@ -0,0 +1,349 @@ +//-------------------------------------------------------------------------------------- +// DirectXTKSimpleSample.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXTKSimpleSample.h" + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + // Create DirectXTK for Audio objects + AUDIO_ENGINE_FLAGS eflags = AudioEngine_UseMasteringLimiter; +#ifdef _DEBUG + eflags = eflags | AudioEngine_Debug; +#endif + + m_audEngine = std::make_unique(eflags); + + m_audioEvent = 0; + m_audioTimerAcc = 10.f; + + m_waveBank = std::make_unique(m_audEngine.get(), L"xmadroid.xwb"); + m_soundEffect = std::make_unique(m_audEngine.get(), L"MusicMono_xma.wav"); + m_effect1 = m_soundEffect->CreateInstance(); + m_effect2 = m_waveBank->CreateInstance(10); + + m_effect1->Play(true); + m_effect2->Play(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + // Only update audio engine once per frame + if (!m_audEngine->Update()) + { + if (m_audEngine->IsCriticalError()) + { + // This would only happen if we were rendering to a headset that was disconnected + // This sample always renders to the 'default' system audio device, not to headsets + assert(false); + } + } + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + Vector3 eye(0.0f, 0.7f, 1.5f); + Vector3 at(0.0f, -0.1f, 0.0f); + + m_view = Matrix::CreateLookAt(eye, at, Vector3::UnitY); + + m_world = Matrix::CreateRotationY(float(timer.GetTotalSeconds() * XM_PIDIV4)); + + m_batchEffect->SetView(m_view); + m_batchEffect->SetWorld(Matrix::Identity); + + m_audioTimerAcc -= (float)timer.GetElapsedSeconds(); + if (m_audioTimerAcc < 0) + { + m_audioTimerAcc = 4.f; + + m_waveBank->Play(m_audioEvent++); + + if (m_audioEvent >= 11) + m_audioEvent = 0; + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + auto size = m_deviceResources->GetOutputSize(); + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Draw procedurally generated dynamic grid + const XMVECTORF32 xaxis = { 20.f, 0.f, 0.f }; + const XMVECTORF32 yaxis = { 0.f, 0.f, 20.f }; + DrawGrid(xaxis, yaxis, g_XMZero, 20, 20, Colors::Gray); + + // Draw sprite + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw sprite"); + m_sprites->Begin(); + m_sprites->Draw(m_texture2.Get(), XMFLOAT2(float(safeRect.left), float(safeRect.top + 50)), nullptr, Colors::White); + + m_font->DrawString(m_sprites.get(), L"DirectXTK Simple Sample", + XMFLOAT2(float(safeRect.left), float(safeRect.top)), Colors::Yellow); + m_sprites->End(); + PIXEndEvent(context); + + // Draw 3D object + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw teapot"); + XMMATRIX local = m_world * Matrix::CreateTranslation(-2.f, -2.f, -4.f); + m_shape->Draw(local, m_view, m_projection, Colors::White, m_texture1.Get()); + PIXEndEvent(context); + + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw model"); + const XMVECTORF32 scale = { 0.01f, 0.01f, 0.01f }; + const XMVECTORF32 translate = { 3.f, -2.f, -4.f }; + XMVECTOR rotate = Quaternion::CreateFromYawPitchRoll(XM_PI / 2.f, 0.f, -XM_PI / 2.f); + local = m_world * XMMatrixTransformation(g_XMZero, Quaternion::Identity, scale, g_XMZero, rotate, translate); + m_model->Draw(context, *m_states, local, m_view, m_projection); + PIXEndEvent(context); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, Colors::CornflowerBlue); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} + +void XM_CALLCONV Sample::DrawGrid(FXMVECTOR xAxis, FXMVECTOR yAxis, FXMVECTOR origin, size_t xdivs, size_t ydivs, GXMVECTOR color) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw grid"); + + context->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF); + context->OMSetDepthStencilState(m_states->DepthNone(), 0); + context->RSSetState(m_states->CullCounterClockwise()); + + m_batchEffect->Apply(context); + + context->IASetInputLayout(m_batchInputLayout.Get()); + + m_batch->Begin(); + + xdivs = std::max(1, xdivs); + ydivs = std::max(1, ydivs); + + for (size_t i = 0; i <= xdivs; ++i) + { + float fPercent = float(i) / float(xdivs); + fPercent = (fPercent * 2.0f) - 1.0f; + XMVECTOR vScale = XMVectorScale(xAxis, fPercent); + vScale = XMVectorAdd(vScale, origin); + + VertexPositionColor v1(XMVectorSubtract(vScale, yAxis), color); + VertexPositionColor v2(XMVectorAdd(vScale, yAxis), color); + m_batch->DrawLine(v1, v2); + } + + for (size_t i = 0; i <= ydivs; i++) + { + float fPercent = float(i) / float(ydivs); + fPercent = (fPercent * 2.0f) - 1.0f; + XMVECTOR vScale = XMVectorScale(yAxis, fPercent); + vScale = XMVectorAdd(vScale, origin); + + VertexPositionColor v1(XMVectorSubtract(vScale, xAxis), color); + VertexPositionColor v2(XMVectorAdd(vScale, xAxis), color); + m_batch->DrawLine(v1, v2); + } + + m_batch->End(); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + m_audEngine->Suspend(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + + m_audEngine->Resume(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_states = std::make_unique(device); + + m_fxFactory = std::make_unique(device); + + m_sprites = std::make_unique(context); + + m_batch = std::make_unique>(context); + + m_batchEffect = std::make_unique(device); + m_batchEffect->SetVertexColorEnabled(true); + + { + void const* shaderByteCode; + size_t byteCodeLength; + + m_batchEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); + + DX::ThrowIfFailed( + device->CreateInputLayout(VertexPositionColor::InputElements, + VertexPositionColor::InputElementCount, + shaderByteCode, byteCodeLength, + m_batchInputLayout.ReleaseAndGetAddressOf()) + ); + } + + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + + m_shape = GeometricPrimitive::CreateTeapot(context, 4.f, 8); + + // SDKMESH has to use clockwise winding with right-handed coordinates, so textures are flipped in U + m_model = Model::CreateFromSDKMESH(device, L"tiny.sdkmesh", *m_fxFactory); + + // Load textures + void *grfxMemory = nullptr; // we just leak the graphics memory... + + DX::ThrowIfFailed( + Xbox::CreateDDSTextureFromFile(device, L"assets\\seafloor.dds", nullptr, m_texture1.ReleaseAndGetAddressOf(), &grfxMemory) + ); + + DX::ThrowIfFailed( + Xbox::CreateDDSTextureFromFile(device, L"assets\\windowslogo.dds", nullptr, m_texture2.ReleaseAndGetAddressOf(), &grfxMemory) + ); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + float aspectRatio = float(size.right) / float(size.bottom); + float fovAngleY = 70.0f * XM_PI / 180.0f; + + // This is a simple example of change that can be made when the app is in + // portrait or snapped view. + if (aspectRatio < 1.0f) + { + fovAngleY *= 2.0f; + } + + // This sample makes use of a right-handed coordinate system using row-major matrices. + m_projection = Matrix::CreatePerspectiveFieldOfView( + fovAngleY, + aspectRatio, + 0.01f, + 100.0f + ); + + m_batchEffect->SetProjection(m_projection); +} +#pragma endregion + diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.h new file mode 100644 index 0000000000000000000000000000000000000000..a54cf62a3885fb9919bab3f1b224e26770ce979f --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.h @@ -0,0 +1,81 @@ +//-------------------------------------------------------------------------------------- +// DirectXTKSimpleSample.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void XM_CALLCONV DrawGrid(DirectX::FXMVECTOR xAxis, DirectX::FXMVECTOR yAxis, DirectX::FXMVECTOR origin, size_t xdivs, size_t ydivs, DirectX::GXMVECTOR color); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_states; + std::unique_ptr m_batchEffect; + std::unique_ptr m_fxFactory; + std::unique_ptr m_shape; + std::unique_ptr m_model; + std::unique_ptr> m_batch; + std::unique_ptr m_sprites; + std::unique_ptr m_font; + + std::unique_ptr m_audEngine; + std::unique_ptr m_waveBank; + std::unique_ptr m_soundEffect; + std::unique_ptr m_effect1; + std::unique_ptr m_effect2; + + Microsoft::WRL::ComPtr m_texture1; + Microsoft::WRL::ComPtr m_texture2; + Microsoft::WRL::ComPtr m_batchInputLayout; + + uint32_t m_audioEvent; + float m_audioTimerAcc; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_projection; +}; diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.sln b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.sln new file mode 100644 index 0000000000000000000000000000000000000000..9c63d5ea891765896f6c0413615c9eaca08a17a0 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTKSimpleSample", "DirectXTKSimpleSample.vcxproj", "{52293090-A49D-442D-BB48-186FA1A749E9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {52293090-A49D-442D-BB48-186FA1A749E9}.Debug|Durango.ActiveCfg = Debug|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Debug|Durango.Build.0 = Debug|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Debug|Durango.Deploy.0 = Debug|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Profile|Durango.ActiveCfg = Profile|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Profile|Durango.Build.0 = Profile|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Profile|Durango.Deploy.0 = Profile|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Release|Durango.ActiveCfg = Release|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Release|Durango.Build.0 = Release|Durango + {52293090-A49D-442D-BB48-186FA1A749E9}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.vcxproj b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..a815ff6656358e78d0413cf31ce79bcf69f17da8 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.vcxproj @@ -0,0 +1,228 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + DirectXTKSimpleSample + {52293090-a49d-442d-bb48-186fa1a749e9} + en-US + Win32Proj + title + + v140 + 11.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.vcxproj.filters b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..65ff39fa29b05fd143b13ac6fe2b893385bcce31 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/DirectXTKSimpleSample.vcxproj.filters @@ -0,0 +1,79 @@ + + + + + 0d205524-6e0d-4cbf-9ac5-c4b34da5b050 + + + 70f16a1c-a386-4c8b-a61b-653c9b86a270 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + + + + + Common + + + Common + + + Common + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Main.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6da2ced94ea6ec1c21f9a3e3054a99c8a643b452 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXTKSimpleSample.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Package.appxmanifest b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..23e16801667ff6c56a2b7087cd7c7debb1e5af2f --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + DirectXTKSimpleSample + Xbox Advanced Technology Group + Assets\StoreLogo.png + DirectXTKSimpleSample + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Readme.docx b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..2b2241d525d4c527587b39933b69ed6efe4863b0 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/StepTimer.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Telemetry.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/pch.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample/pch.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..2ea6db22f4b85624ad20591a9cd3fddd9eea46f1 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample/pch.h @@ -0,0 +1,76 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "Audio.h" +#include "CommonStates.h" +#include "DDSTextureLoader.h" +#include "Effects.h" +#include "GamePad.h" +#include "GeometricPrimitive.h" +#include "GraphicsMemory.h" +#include "Model.h" +#include "PrimitiveBatch.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "VertexTypes.h" +#include "XboxDDSTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/Logo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/seafloor.dds b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/seafloor.dds new file mode 100644 index 0000000000000000000000000000000000000000..02db0a0c4b947d29c3a6bf9eeb61ce2a3c27d2ee Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/seafloor.dds differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/windowslogo.dds b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/windowslogo.dds new file mode 100644 index 0000000000000000000000000000000000000000..38f6dc861d598dfb51bdea5ed1a62234cf77a600 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Assets/windowslogo.dds differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DeviceResources.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DeviceResources.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7acb7d8584bfdef3abae2e866bbb59f9e8b15fd4 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.cpp @@ -0,0 +1,421 @@ +//-------------------------------------------------------------------------------------- +// DirectXTKSimpleSample12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXTKSimpleSample12.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; +using namespace DirectX::SimpleMath; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + // Create DirectXTK for Audio objects + AUDIO_ENGINE_FLAGS eflags = AudioEngine_UseMasteringLimiter; +#ifdef _DEBUG + eflags = eflags | AudioEngine_Debug; +#endif + + m_audEngine = std::make_unique(eflags); + + m_audioEvent = 0; + m_audioTimerAcc = 10.f; + + m_waveBank = std::make_unique(m_audEngine.get(), L"xmadroid.xwb"); + m_soundEffect = std::make_unique(m_audEngine.get(), L"MusicMono_xma.wav"); + m_effect1 = m_soundEffect->CreateInstance(); + m_effect2 = m_waveBank->CreateInstance(10); + + m_effect1->Play(true); + m_effect2->Play(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + // Only update audio engine once per frame + if (!m_audEngine->Update()) + { + if (m_audEngine->IsCriticalError()) + { + // This would only happen if we were rendering to a headset that was disconnected + // This sample always renders to the 'default' system audio device, not to headsets + assert(false); + } + } + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + Vector3 eye(0.0f, 0.7f, 1.5f); + Vector3 at(0.0f, -0.1f, 0.0f); + + m_view = Matrix::CreateLookAt(eye, at, Vector3::UnitY); + + m_world = Matrix::CreateRotationY(float(timer.GetTotalSeconds() * XM_PIDIV4)); + + m_lineEffect->SetView(m_view); + m_lineEffect->SetWorld(Matrix::Identity); + + m_shapeEffect->SetView(m_view); + + m_audioTimerAcc -= (float)timer.GetElapsedSeconds(); + if (m_audioTimerAcc < 0) + { + m_audioTimerAcc = 4.f; + + m_waveBank->Play(m_audioEvent++); + + if (m_audioEvent >= 11) + m_audioEvent = 0; + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + auto size = m_deviceResources->GetOutputSize(); + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Draw procedurally generated dynamic grid + const XMVECTORF32 xaxis = { 20.f, 0.f, 0.f }; + const XMVECTORF32 yaxis = { 0.f, 0.f, 20.f }; + DrawGrid(xaxis, yaxis, g_XMZero, 20, 20, Colors::Gray); + + // Set the descriptor heaps + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap(), m_states->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Draw sprite + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw sprite"); + m_sprites->Begin(commandList); + m_sprites->Draw(m_resourceDescriptors->GetGpuHandle(Descriptors::WindowsLogo), GetTextureSize(m_texture2.Get()), + XMFLOAT2(float(safeRect.left), float(safeRect.top + 50))); + + m_font->DrawString(m_sprites.get(), L"DirectXTK Simple Sample", + XMFLOAT2(float(safeRect.left), float(safeRect.top)), Colors::Yellow); + m_sprites->End(); + PIXEndEvent(commandList); + + // Draw 3D object + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw teapot"); + XMMATRIX local = m_world * Matrix::CreateTranslation(-2.f, -2.f, -4.f); + m_shapeEffect->SetWorld(local); + m_shapeEffect->Apply(commandList); + m_shape->Draw(commandList); + PIXEndEvent(commandList); + + // Draw model + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw model"); + const XMVECTORF32 scale = { 0.01f, 0.01f, 0.01f }; + const XMVECTORF32 translate = { 3.f, -2.f, -4.f }; + XMVECTOR rotate = Quaternion::CreateFromYawPitchRoll(XM_PI / 2.f, 0.f, -XM_PI / 2.f); + local = m_world * XMMatrixTransformation(g_XMZero, Quaternion::Identity, scale, g_XMZero, rotate, translate); + Model::UpdateEffectMatrices(m_modelEffects, local, m_view, m_projection); + heaps[0] = m_modelResources->Heap(); + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + m_model->Draw(commandList, m_modelEffects.begin()); + PIXEndEvent(commandList); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + commandList->ClearRenderTargetView(rtvDescriptor, Colors::CornflowerBlue, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} + +void XM_CALLCONV Sample::DrawGrid(FXMVECTOR xAxis, FXMVECTOR yAxis, FXMVECTOR origin, size_t xdivs, size_t ydivs, GXMVECTOR color) +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw grid"); + + m_lineEffect->Apply(commandList); + + m_batch->Begin(commandList); + + xdivs = std::max(1, xdivs); + ydivs = std::max(1, ydivs); + + for (size_t i = 0; i <= xdivs; ++i) + { + float fPercent = float(i) / float(xdivs); + fPercent = (fPercent * 2.0f) - 1.0f; + XMVECTOR vScale = XMVectorScale(xAxis, fPercent); + vScale = XMVectorAdd(vScale, origin); + + VertexPositionColor v1(XMVectorSubtract(vScale, yAxis), color); + VertexPositionColor v2(XMVectorAdd(vScale, yAxis), color); + m_batch->DrawLine(v1, v2); + } + + for (size_t i = 0; i <= ydivs; i++) + { + float fPercent = float(i) / float(ydivs); + fPercent = (fPercent * 2.0f) - 1.0f; + XMVECTOR vScale = XMVectorScale(yAxis, fPercent); + vScale = XMVectorAdd(vScale, origin); + + VertexPositionColor v1(XMVectorSubtract(vScale, xAxis), color); + VertexPositionColor v2(XMVectorAdd(vScale, xAxis), color); + m_batch->DrawLine(v1, v2); + } + + m_batch->End(); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + m_audEngine->Suspend(); + + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + + m_audEngine->Resume(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + void *grfxMemory = nullptr; // we just leak the graphics memory... + + DX::ThrowIfFailed( + Xbox::CreateDDSTextureFromFile(device, L"assets\\seafloor.dds", m_texture1.ReleaseAndGetAddressOf(), &grfxMemory) + ); + + DX::ThrowIfFailed( + Xbox::CreateDDSTextureFromFile(device, L"assets\\windowslogo.dds", m_texture2.ReleaseAndGetAddressOf(), &grfxMemory) + ); + + m_resourceDescriptors = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); + + m_states = std::make_unique(device); + + CreateShaderResourceView(device, m_texture1.Get(), m_resourceDescriptors->GetCpuHandle(Descriptors::SeaFloor)); + + CreateShaderResourceView(device, m_texture2.Get(), m_resourceDescriptors->GetCpuHandle(Descriptors::WindowsLogo)); + + m_batch = std::make_unique>(device); + + m_shape = GeometricPrimitive::CreateTeapot(4.f, 8); + + // SDKMESH has to use clockwise winding with right-handed coordinates, so textures are flipped in U + m_model = Model::CreateFromSDKMESH(L"tiny.sdkmesh"); + + { + ResourceUploadBatch resourceUpload(device); + + resourceUpload.Begin(); + + RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + + { + EffectPipelineStateDescription pd( + &VertexPositionColor::InputLayout, + CommonStates::Opaque, + CommonStates::DepthNone, + CommonStates::CullNone, + rtState, + D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE); + + m_lineEffect = std::make_unique(device, EffectFlags::VertexColor, pd); + } + + { + EffectPipelineStateDescription pd( + &GeometricPrimitive::VertexType::InputLayout, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullNone, + rtState); + + m_shapeEffect = std::make_unique(device, EffectFlags::PerPixelLighting | EffectFlags::Texture, pd); + m_shapeEffect->EnableDefaultLighting(); + m_shapeEffect->SetTexture(m_resourceDescriptors->GetGpuHandle(Descriptors::SeaFloor), m_states->AnisotropicWrap()); + } + + { + SpriteBatchPipelineStateDescription pd(rtState); + + m_sprites = std::make_unique(device, resourceUpload, pd); + } + + m_modelResources = m_model->LoadTextures(device, resourceUpload, L"assets\\"); + + { + EffectPipelineStateDescription psd( + nullptr, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, // Using RH coordinates, and SDKMESH is in LH coordiantes + rtState); + + EffectPipelineStateDescription alphapsd( + nullptr, + CommonStates::NonPremultiplied, // Using straight alpha + CommonStates::DepthRead, + CommonStates::CullClockwise, // Using RH coordinates, and SDKMESH is in LH coordiantes + rtState); + + m_modelEffects = m_model->CreateEffects(psd, alphapsd, m_modelResources->Heap(), m_states->Heap()); + } + + m_font = std::make_unique(device, resourceUpload, + L"SegoeUI_18.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::SegoeFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::SegoeFont)); + + // Upload the resources to the GPU. + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + + // Wait for the upload thread to terminate + uploadResourcesFinished.wait(); + } +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + float aspectRatio = float(size.right) / float(size.bottom); + float fovAngleY = 70.0f * XM_PI / 180.0f; + + // This is a simple example of change that can be made when the app is in + // portrait or snapped view. + if (aspectRatio < 1.0f) + { + fovAngleY *= 2.0f; + } + + // This sample makes use of a right-handed coordinate system using row-major matrices. + m_projection = Matrix::CreatePerspectiveFieldOfView( + fovAngleY, + aspectRatio, + 0.01f, + 100.0f + ); + + m_lineEffect->SetProjection(m_projection); + m_shapeEffect->SetProjection(m_projection); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_sprites->SetViewport(viewport); +} +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.h new file mode 100644 index 0000000000000000000000000000000000000000..7c7410f2050ad56f177c2b3be32956fd75f587f6 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.h @@ -0,0 +1,94 @@ +//-------------------------------------------------------------------------------------- +// DirectXTKSimpleSample12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void XM_CALLCONV DrawGrid(DirectX::FXMVECTOR xAxis, DirectX::FXMVECTOR yAxis, DirectX::FXMVECTOR origin, size_t xdivs, size_t ydivs, DirectX::GXMVECTOR color); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_resourceDescriptors; + std::unique_ptr m_states; + std::unique_ptr m_lineEffect; + std::unique_ptr> m_batch; + std::unique_ptr m_shapeEffect; + std::unique_ptr m_model; + std::vector> m_modelEffects; + std::unique_ptr m_modelResources; + std::unique_ptr m_shape; + std::unique_ptr m_sprites; + std::unique_ptr m_font; + + std::unique_ptr m_audEngine; + std::unique_ptr m_waveBank; + std::unique_ptr m_soundEffect; + std::unique_ptr m_effect1; + std::unique_ptr m_effect2; + + Microsoft::WRL::ComPtr m_texture1; + Microsoft::WRL::ComPtr m_texture2; + + uint32_t m_audioEvent; + float m_audioTimerAcc; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_projection; + + // Descriptors + enum Descriptors + { + WindowsLogo, + SeaFloor, + SegoeFont, + Count = 256 + }; +}; diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.sln b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.sln new file mode 100644 index 0000000000000000000000000000000000000000..98dc7a4748733ffda8c7d6b76858bc74e55f4978 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTKSimpleSample12", "DirectXTKSimpleSample12.vcxproj", "{79F86052-E31C-45BD-9C55-01B41E58C3AE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Debug|Durango.ActiveCfg = Debug|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Debug|Durango.Build.0 = Debug|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Debug|Durango.Deploy.0 = Debug|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Profile|Durango.ActiveCfg = Profile|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Profile|Durango.Build.0 = Profile|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Profile|Durango.Deploy.0 = Profile|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Release|Durango.ActiveCfg = Release|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Release|Durango.Build.0 = Release|Durango + {79F86052-E31C-45BD-9C55-01B41E58C3AE}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.vcxproj b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..14a1862c144e9b9f07c1b57fec57dc6c2ca498e0 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.vcxproj @@ -0,0 +1,228 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + DirectXTKSimpleSample12 + {79f86052-e31c-45bd-9c55-01b41e58c3ae} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.vcxproj.filters b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..bdb15e06a332c88cd48533a811803406977d3f10 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/DirectXTKSimpleSample12.vcxproj.filters @@ -0,0 +1,79 @@ + + + + + efa9f5c7-f1c8-42ce-b3d6-d5427aacbfc3 + + + ed4909a5-af18-4328-8eff-136e46ba9983 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + + + + + Common + + + Common + + + Common + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + Assets + + + Assets + + + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Main.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e9ba7e71d6534d5ea11a1c9054eb7eb91121366 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXTKSimpleSample12.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Package.appxmanifest b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..f6f14f66458c6cfe2bbdd50aa5212be1a434c463 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + DirectXTKSimpleSample12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + DirectXTKSimpleSample12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Readme.docx b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..ae28a06b9ec92b26266f5b4f6206cd37d7cd7e42 Binary files /dev/null and b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/StepTimer.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Telemetry.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/pch.cpp b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/pch.h b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..9d3fa3815d0802bafe5f959ff6bc0de3a88fc979 --- /dev/null +++ b/XDKSamples/IntroGraphics/DirectXTKSimpleSample12/pch.h @@ -0,0 +1,79 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "Audio.h" +#include "CommonStates.h" +#include "DirectXHelpers.h" +#include "DDSTextureLoader.h" +#include "DescriptorHeap.h" +#include "Effects.h" +#include "GamePad.h" +#include "GeometricPrimitive.h" +#include "GraphicsMemory.h" +#include "Model.h" +#include "PrimitiveBatch.h" +#include "ResourceUploadBatch.h" +#include "RenderTargetState.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "VertexTypes.h" +#include "XboxDDSTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierDS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierDS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierDS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_fracEven.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_fracEven.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_fracEven.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_fracOdd.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_fracOdd.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_fracOdd.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_int.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_int.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierHS_int.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierPS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierPS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierVS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/BezierVS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleBezier/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/SimpleBezier.hlsli b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SimpleBezier.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..bd960e4e0483f26f3c17dfb8e872d079d37162a3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SimpleBezier.hlsli @@ -0,0 +1,229 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.hlsli +// +// Shader demonstrating DirectX 11 tesselation of a bezier surface +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +// The input patch size. In this sample, it is 16 control points. +// This value should match the call to IASetPrimitiveTopology() +#define INPUT_PATCH_SIZE 16 + +// The output patch size. In this sample, it is also 16 control points. +#define OUTPUT_PATCH_SIZE 16 + +//-------------------------------------------------------------------------------------- +// Constant Buffers +//-------------------------------------------------------------------------------------- +cbuffer cbPerFrame : register(b0) +{ + row_major matrix g_mViewProjection; + float3 g_cameraWorldPos; + float g_tessellationFactor; +}; + +//-------------------------------------------------------------------------------------- +// Vertex shader section +//-------------------------------------------------------------------------------------- +struct VS_CONTROL_POINT_INPUT +{ + float3 pos : POSITION; +}; + +struct VS_CONTROL_POINT_OUTPUT +{ + float3 pos : POSITION; +}; + +//-------------------------------------------------------------------------------------- +// This simple vertex shader passes the control points straight through to the +// hull shader. In a more complex scene, you might transform the control points +// or perform skinning at this step. +// +// The input to the vertex shader comes from the vertex buffer. +// +// The output from the vertex shader will go into the hull shader. +//-------------------------------------------------------------------------------------- +VS_CONTROL_POINT_OUTPUT BezierVS(VS_CONTROL_POINT_INPUT Input) +{ + VS_CONTROL_POINT_OUTPUT output; + + output.pos = Input.pos; + + return output; +} + +//-------------------------------------------------------------------------------------- +// Constant data function for the BezierHS. This is executed once per patch. +//-------------------------------------------------------------------------------------- +struct HS_CONSTANT_DATA_OUTPUT +{ + float Edges[4] : SV_TessFactor; + float Inside[2] : SV_InsideTessFactor; +}; + +struct HS_OUTPUT +{ + float3 pos : BEZIERPOS; +}; + +//-------------------------------------------------------------------------------------- +// This constant hull shader is executed once per patch. For the simple Mobius strip +// model, it will be executed 4 times. In this sample, we set the tessellation factor +// via SV_TessFactor and SV_InsideTessFactor for each patch. In a more complex scene, +// you might calculate a variable tessellation factor based on the camera's distance. +//-------------------------------------------------------------------------------------- +HS_CONSTANT_DATA_OUTPUT BezierConstantHS(InputPatch< VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE > ip, + uint PatchID : SV_PrimitiveID) +{ + HS_CONSTANT_DATA_OUTPUT output; + + float TessAmount = g_tessellationFactor; + + output.Edges[0] = output.Edges[1] = output.Edges[2] = output.Edges[3] = TessAmount; + output.Inside[0] = output.Inside[1] = TessAmount; + + return output; +} + +//-------------------------------------------------------------------------------------- +// BezierHS +// The hull shader is called once per output control point, which is specified with +// outputcontrolpoints. For this sample, we take the control points from the vertex +// shader and pass them directly off to the domain shader. In a more complex scene, +// you might perform a basis conversion from the input control points into a Bezier +// patch, such as the SubD11 SimpleBezier. +// +// The input to the hull shader comes from the vertex shader. +// +// The output from the hull shader will go to the domain shader. +// The tessellation factor, topology, and partition mode will go to the fixed function +// tessellator stage to calculate the UVW barycentric coordinates and domain points. +//-------------------------------------------------------------------------------------- +[domain("quad")] +[partitioning(BEZIER_HS_PARTITION)] +[outputtopology("triangle_cw")] +[outputcontrolpoints(OUTPUT_PATCH_SIZE)] +[patchconstantfunc("BezierConstantHS")] +HS_OUTPUT BezierHS(InputPatch< VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE > p, + uint i : SV_OutputControlPointID, + uint PatchID : SV_PrimitiveID) +{ + HS_OUTPUT output; + output.pos = p[i].pos; + return output; +} + +//-------------------------------------------------------------------------------------- +// Bezier evaluation domain shader section +//-------------------------------------------------------------------------------------- +struct DS_OUTPUT +{ + float4 pos : SV_POSITION; + float3 worldPos : WORLDPOS; + float3 normal : NORMAL; +}; + +//-------------------------------------------------------------------------------------- +float4 BernsteinBasis(float t) +{ + float invT = 1.0f - t; + + return float4(invT * invT * invT, + 3.0f * t * invT * invT, + 3.0f * t * t * invT, + t * t * t); +} + +//-------------------------------------------------------------------------------------- +float4 dBernsteinBasis(float t) +{ + float invT = 1.0f - t; + + return float4(-3 * invT * invT, + 3 * invT * invT - 6 * t * invT, + 6 * t * invT - 3 * t * t, + 3 * t * t); +} + +//-------------------------------------------------------------------------------------- +float3 EvaluateBezier(const OutputPatch< HS_OUTPUT, OUTPUT_PATCH_SIZE > BezPatch, + float4 BasisU, + float4 BasisV) +{ + float3 value = float3(0, 0, 0); + value = BasisV.x * (BezPatch[0].pos * BasisU.x + BezPatch[1].pos * BasisU.y + BezPatch[2].pos * BasisU.z + BezPatch[3].pos * BasisU.w); + value += BasisV.y * (BezPatch[4].pos * BasisU.x + BezPatch[5].pos * BasisU.y + BezPatch[6].pos * BasisU.z + BezPatch[7].pos * BasisU.w); + value += BasisV.z * (BezPatch[8].pos * BasisU.x + BezPatch[9].pos * BasisU.y + BezPatch[10].pos * BasisU.z + BezPatch[11].pos * BasisU.w); + value += BasisV.w * (BezPatch[12].pos * BasisU.x + BezPatch[13].pos * BasisU.y + BezPatch[14].pos * BasisU.z + BezPatch[15].pos * BasisU.w); + + return value; +} + + +//-------------------------------------------------------------------------------------- +// The domain shader is run once per vertex and calculates the final vertex's position +// and attributes. It receives the UVW from the fixed function tessellator and the +// control point outputs from the hull shader. Since we are using the DirectX 11 +// Tessellation pipeline, it is the domain shader's responsibility to calculate the +// final SV_POSITION for each vertex. In this sample, we evaluate the vertex's +// position using a Bernstein polynomial and the normal is calculated as the cross +// product of the U and V derivatives. +// +// The input SV_DomainLocation to the domain shader comes from fixed function +// tessellator. And the OutputPatch comes from the hull shader. From these, you +// must calculate the final vertex position, color, texcoords, and other attributes. +// +// The output from the domain shader will be a vertex that will go to the video card's +// rasterization pipeline and get drawn to the screen. +//-------------------------------------------------------------------------------------- +[domain("quad")] +DS_OUTPUT BezierDS(HS_CONSTANT_DATA_OUTPUT input, + float2 UV : SV_DomainLocation, + const OutputPatch< HS_OUTPUT, OUTPUT_PATCH_SIZE > BezPatch) +{ + float4 BasisU = BernsteinBasis(UV.x); + float4 BasisV = BernsteinBasis(UV.y); + float4 dBasisU = dBernsteinBasis(UV.x); + float4 dBasisV = dBernsteinBasis(UV.y); + + float3 worldPos = EvaluateBezier(BezPatch, BasisU, BasisV); + float3 tangent = EvaluateBezier(BezPatch, dBasisU, BasisV); + float3 biTangent = EvaluateBezier(BezPatch, BasisU, dBasisV); + float3 normal = normalize(cross(tangent, biTangent)); + + DS_OUTPUT output; + output.pos = mul(float4(worldPos, 1), g_mViewProjection); + output.worldPos = worldPos; + output.normal = normal; + + return output; +} + +//-------------------------------------------------------------------------------------- +// Smooth shading pixel shader section +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// The pixel shader works the same as it would in a normal graphics pipeline. +// In this sample, it performs very simple N dot L lighting. +//-------------------------------------------------------------------------------------- +float4 BezierPS(DS_OUTPUT Input) : SV_TARGET +{ + float3 N = normalize(Input.normal); + float3 L = normalize(Input.worldPos - g_cameraWorldPos); + return abs(dot(N, L)) * float4(1, 0, 0, 1); +} + +//-------------------------------------------------------------------------------------- +// Solid color shading pixel shader (used for wireframe overlay) +//-------------------------------------------------------------------------------------- +float4 SolidColorPS(DS_OUTPUT Input) : SV_TARGET +{ + // Return a dark green color + return float4(0, 0.25, 0, 1); +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/SolidColorPS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SolidColorPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SolidColorPS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleBezier/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleBezier/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleBezier/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleBezier/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Main.cpp b/XDKSamples/IntroGraphics/SimpleBezier/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aae3a3307e6c2e2902bb260de83e81f2925d56a1 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleBezier.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleBezier/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..d6ba125973e7640faa59d2e534bfca1c7d609516 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleBezier + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleBezier + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Readme.docx b/XDKSamples/IntroGraphics/SimpleBezier/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..3bf735e5d477fcd8221294dd36e5a5756154f5fb Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.cpp b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..969525c3a23006882747cdf96611bdc8b4e9cfc7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.cpp @@ -0,0 +1,503 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleBezier.h" + +#include "DirectXHelpers.h" +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#pragma region Globals +// Global variables +namespace +{ + // Help menu text + const wchar_t* c_sampleTitle = L"Simple Bezier Sample"; + const wchar_t* c_sampleDescription = L"Demonstrates how to create hull and domain shaders to draw a\ntessellated Bezier surface representing a Mobius strip."; + const ATG::HelpButtonAssignment c_helpButtons[] = { + { ATG::HelpID::MENU_BUTTON, L"Show/Hide Help" }, + { ATG::HelpID::VIEW_BUTTON, L"Exit" }, + { ATG::HelpID::LEFT_STICK, L"Rotate Camera" }, + { ATG::HelpID::LEFT_TRIGGER, L"Decrease Subdivisions" }, + { ATG::HelpID::RIGHT_TRIGGER, L"Increase Subdivisions" }, + { ATG::HelpID::Y_BUTTON, L"Toggle Wireframe" }, + { ATG::HelpID::A_BUTTON, L"Fractional Partitioning (Even)" }, + { ATG::HelpID::B_BUTTON, L"Fractional Partitioning (Odd)" }, + { ATG::HelpID::X_BUTTON, L"Integer Partitioning" }, + }; + + // Min and max divisions of the patch per side for the slider control + const float c_minDivs = 4; + const float c_maxDivs = 16; + // Startup subdivisions per side + const float c_defaultSubdivs = 8.0f; + // Camera's rotation angle per step + const float c_rotationAnglePerStep = XM_2PI / 360.0f; + + // Initial camera setup + const XMVECTOR c_cameraEye = XMVectorSet(0.0f, 0.45f, 2.7f, 0.0f); + const XMVECTOR c_cameraAt = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); + const XMVECTOR c_cameraUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); + + // Draw the mesh with shaded triangles at start. + const bool c_defaultWireframeRendering = false; + + // Simple Bezier patch for a Mobius strip. + // 4 patches with 16 control points each. + const XMFLOAT3 c_mobiusStrip[64] = { + { 1.0f, -0.5f, 0.0f }, + { 1.0f, -0.5f, 0.5f }, + { 0.5f, -0.3536f, 1.354f }, + { 0.0f, -0.3536f, 1.354f }, + { 1.0f, -0.1667f, 0.0f }, + { 1.0f, -0.1667f, 0.5f }, + { 0.5f, -0.1179f, 1.118f }, + { 0.0f, -0.1179f, 1.118f }, + { 1.0f, 0.1667f, 0.0f }, + { 1.0f, 0.1667f, 0.5f }, + { 0.5f, 0.1179f, 0.8821f }, + { 0.0f, 0.1179f, 0.8821f }, + { 1.0f, 0.5f, 0.0f }, + { 1.0f, 0.5f, 0.5f }, + { 0.5f, 0.3536f, 0.6464f }, + { 0.0f, 0.3536f, 0.6464f }, + { 0.0f, -0.3536f, 1.354f }, + { -0.5f, -0.3536f, 1.354f }, + { -1.5f, 0.0f, 0.5f }, + { -1.5f, 0.0f, 0.0f }, + { 0.0f, -0.1179f, 1.118f }, + { -0.5f, -0.1179f, 1.118f }, + { -1.167f, 0.0f, 0.5f }, + { -1.167f, 0.0f, 0.0f }, + { 0.0f, 0.1179f, 0.8821f }, + { -0.5f, 0.1179f, 0.8821f }, + { -0.8333f, 0.0f, 0.5f }, + { -0.8333f, 0.0f, 0.0f }, + { 0.0f, 0.3536f, 0.6464f }, + { -0.5f, 0.3536f, 0.6464f }, + { -0.5f, 0.0f, 0.5f }, + { -0.5f, 0.0f, 0.0f }, + { -1.5f, 0.0f, 0.0f }, + { -1.5f, 0.0f, -0.5f }, + { -0.5f, 0.3536f, -1.354f }, + { 0.0f, 0.3536f, -1.354f }, + { -1.167f, 0.0f, 0.0f }, + { -1.167f, 0.0f, -0.5f }, + { -0.5f, 0.1179f, -1.118f }, + { 0.0f, 0.1179f, -1.118f }, + { -0.8333f, 0.0f, 0.0f }, + { -0.8333f, 0.0f, -0.5f }, + { -0.5f, -0.1179f, -0.8821f }, + { 0.0f, -0.1179f, -0.8821f }, + { -0.5f, 0.0f, 0.0f }, + { -0.5f, 0.0f, -0.5f }, + { -0.5f, -0.3536f, -0.6464f }, + { 0.0f, -0.3536f, -0.6464f }, + { 0.0f, 0.3536f, -1.354f }, + { 0.5f, 0.3536f, -1.354f }, + { 1.0f, 0.5f, -0.5f }, + { 1.0f, 0.5f, 0.0f }, + { 0.0f, 0.1179f, -1.118f }, + { 0.5f, 0.1179f, -1.118f }, + { 1.0f, 0.1667f, -0.5f }, + { 1.0f, 0.1667f, 0.0f }, + { 0.0f, -0.1179f, -0.8821f }, + { 0.5f, -0.1179f, -0.8821f }, + { 1.0f, -0.1667f, -0.5f }, + { 1.0f, -0.1667f, 0.0f }, + { 0.0f, -0.3536f, -0.6464f }, + { 0.5f, -0.3536f, -0.6464f }, + { 1.0f, -0.5f, -0.5f }, + { 1.0f, -0.5f, 0.0f }, + }; +} +#pragma endregion + +Sample::Sample() + : m_frame(0) + , m_subdivs(c_defaultSubdivs) + , m_drawWires(c_defaultWireframeRendering) + , m_partitionMode(PartitionMode::PartitionInteger) + , m_showHelp(false) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); + + m_help = std::make_unique(c_sampleTitle, c_sampleDescription, c_helpButtons, _countof(c_helpButtons), true); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = !m_showHelp; + } + else if (m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + m_drawWires = !m_drawWires; + } + else if (m_gamePadButtons.x == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionInteger; + } + else if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionFractionalEven; + } + else if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + if (m_showHelp) + { + m_showHelp = false; + } + else + { + m_partitionMode = PartitionMode::PartitionFractionalOdd; + } + } + + if (pad.IsLeftTriggerPressed()) + { + m_subdivs = std::max(m_subdivs - 0.1f, c_minDivs); + } + + if (pad.IsRightTriggerPressed()) + { + m_subdivs = std::min(m_subdivs + 0.1f, c_maxDivs); + } + + if (pad.thumbSticks.leftX != 0.0f) + { + float rotationAxisY = -pad.thumbSticks.leftX * c_rotationAnglePerStep; + + XMVECTOR eye = XMLoadFloat3(&m_cameraEye); + eye = XMVector3Transform(eye, XMMatrixRotationY(rotationAxisY)); + XMMATRIX view = XMMatrixLookAtLH(eye, c_cameraAt, c_cameraUp); + XMStoreFloat4x4(&m_viewMatrix, view); + XMStoreFloat3(&m_cameraEye, eye); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + if (m_showHelp) + { + //Clear hull and domain shaders so help can render. + context->HSSetShader(nullptr, nullptr, 0); + context->DSSetShader(nullptr, nullptr, 0); + + m_help->Render(); + } + else + { + //Reset state that may have been modified by showing help. + context->OMSetBlendState(m_states->Opaque(), Colors::Black, 0xFFFFFFFF); + context->OMSetDepthStencilState(m_states->DepthDefault(), 0); + + XMMATRIX view = XMLoadFloat4x4(&m_viewMatrix); + XMMATRIX projection = XMLoadFloat4x4(&m_projectionMatrix); + XMMATRIX viewProjectionMatrix = XMMatrixMultiply(view, projection); + + // Update per-frame variables. + auto d3dBuffer = m_cbPerFrame.Get(); + + { + MapGuard mappedResource(context, d3dBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0); + + ConstantBuffer* data = reinterpret_cast(mappedResource.get()); + + XMStoreFloat4x4(&data->viewProjectionMatrix, viewProjectionMatrix); + data->cameraWorldPos = m_cameraEye; + data->tessellationFactor = (float)m_subdivs; + } + + // Render the meshes. + // Bind all of the CBs. + context->VSSetConstantBuffers(0, 1, &d3dBuffer); + context->HSSetConstantBuffers(0, 1, &d3dBuffer); + context->DSSetConstantBuffers(0, 1, &d3dBuffer); + context->PSSetConstantBuffers(0, 1, &d3dBuffer); + + // Set the shaders. + context->VSSetShader(m_vertexShader.Get(), nullptr, 0); + + // For this sample, choose either the "integer", "fractional_even", + // or "fractional_odd" hull shader. + if (m_partitionMode == PartitionMode::PartitionInteger) + { + context->HSSetShader(m_hullShaderInteger.Get(), nullptr, 0); + } + else if (m_partitionMode == PartitionMode::PartitionFractionalEven) + { + context->HSSetShader(m_hullShaderFracEven.Get(), nullptr, 0); + } + else if (m_partitionMode == PartitionMode::PartitionFractionalOdd) + { + context->HSSetShader(m_hullShaderFracOdd.Get(), nullptr, 0); + } + + context->DSSetShader(m_domainShader.Get(), nullptr, 0); + context->GSSetShader(nullptr, nullptr, 0); + + // Optionally draw the wireframe. + if (m_drawWires) + { + context->PSSetShader(m_solidColorPS.Get(), nullptr, 0); + context->RSSetState(m_states->Wireframe()); + } + else + { + context->PSSetShader(m_pixelShader.Get(), nullptr, 0); + context->RSSetState(m_states->CullNone()); + } + + // Set the input assembler. + // This sample uses patches with 16 control points each. + // Although the Mobius strip only needs to use a vertex buffer, + // you can use an index buffer as well by calling IASetIndexBuffer(). + context->IASetInputLayout(m_inputLayout.Get()); + UINT stride = sizeof(XMFLOAT3); + UINT offset = 0; + context->IASetVertexBuffers(0, 1, m_controlPointVB.GetAddressOf(), &stride, &offset); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST); + + // Draw the mesh + context->Draw(_countof(c_mobiusStrip), 0); + } + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + m_states = std::make_unique(device); + + CreateShaders(); + + // Initialize the world and view matrices. + XMMATRIX world = XMMatrixIdentity(); + XMMATRIX view = XMMatrixLookAtLH(c_cameraEye, c_cameraAt, c_cameraUp); + XMStoreFloat4x4(&m_worldMatrix, world); + XMStoreFloat4x4(&m_viewMatrix, view); + XMStoreFloat3(&m_cameraEye, c_cameraEye); + + m_help->RestoreDevice(context); +} + +// Creates and initializes shaders and their data. +void Sample::CreateShaders() +{ + auto device = m_deviceResources->GetD3DDevice(); + + // Load and create shaders. + auto vertexShaderBlob = DX::ReadData(L"BezierVS.cso"); + DX::ThrowIfFailed( + device->CreateVertexShader(vertexShaderBlob.data(), vertexShaderBlob.size(), + nullptr, m_vertexShader.ReleaseAndGetAddressOf())); + + auto hullShaderIntegerBlob = DX::ReadData(L"BezierHS_int.cso"); + DX::ThrowIfFailed( + device->CreateHullShader(hullShaderIntegerBlob.data(), hullShaderIntegerBlob.size(), + nullptr, m_hullShaderInteger.ReleaseAndGetAddressOf())); + + auto hullShaderFracEvenBlob = DX::ReadData(L"BezierHS_fracEven.cso"); + DX::ThrowIfFailed( + device->CreateHullShader(hullShaderFracEvenBlob.data(), hullShaderFracEvenBlob.size(), + nullptr, m_hullShaderFracEven.ReleaseAndGetAddressOf())); + + auto hullShaderFracOddBlob = DX::ReadData(L"BezierHS_fracOdd.cso"); + DX::ThrowIfFailed( + device->CreateHullShader(hullShaderFracOddBlob.data(), hullShaderFracOddBlob.size(), + nullptr, m_hullShaderFracOdd.ReleaseAndGetAddressOf())); + + auto domainShaderBlob = DX::ReadData(L"BezierDS.cso"); + DX::ThrowIfFailed( + device->CreateDomainShader(domainShaderBlob.data(), domainShaderBlob.size(), + nullptr, m_domainShader.ReleaseAndGetAddressOf())); + + auto pixelShaderBlob = DX::ReadData(L"BezierPS.cso"); + DX::ThrowIfFailed( + device->CreatePixelShader(pixelShaderBlob.data(), pixelShaderBlob.size(), + nullptr, m_pixelShader.ReleaseAndGetAddressOf())); + + auto solidColorPSBlob = DX::ReadData(L"SolidColorPS.cso"); + DX::ThrowIfFailed( + device->CreatePixelShader(solidColorPSBlob.data(), solidColorPSBlob.size(), + nullptr, m_solidColorPS.ReleaseAndGetAddressOf())); + + + // Create our vertex input layout. + static const D3D11_INPUT_ELEMENT_DESC c_inputElementDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + DX::ThrowIfFailed( + device->CreateInputLayout(c_inputElementDesc, _countof(c_inputElementDesc), + vertexShaderBlob.data(), vertexShaderBlob.size(), + m_inputLayout.ReleaseAndGetAddressOf())); + + + // Create constant buffers. + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.ByteWidth = sizeof(ConstantBuffer); + + DX::ThrowIfFailed(device->CreateBuffer(&bufferDesc, nullptr, m_cbPerFrame.ReleaseAndGetAddressOf())); + + + // Create vertex buffer. + D3D11_BUFFER_DESC vbDesc = { 0 }; + vbDesc.ByteWidth = sizeof(XMFLOAT3) * ARRAYSIZE(c_mobiusStrip); + vbDesc.Usage = D3D11_USAGE_DEFAULT; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + + D3D11_SUBRESOURCE_DATA vbInitData = { 0 }; + vbInitData.pSysMem = c_mobiusStrip; + + DX::ThrowIfFailed(device->CreateBuffer(&vbDesc, &vbInitData, m_controlPointVB.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + + XMMATRIX projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.01f, 100.0f); + XMStoreFloat4x4(&m_projectionMatrix, projection); + + m_help->SetWindow(size); +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.h b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.h new file mode 100644 index 0000000000000000000000000000000000000000..296c48aea26847cf878bbf54918cfffabeecdd81 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.h @@ -0,0 +1,103 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "ControllerHelp.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateShaders(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Sample objects + struct ConstantBuffer + { + DirectX::XMFLOAT4X4 viewProjectionMatrix; + DirectX::XMFLOAT3 cameraWorldPos; + float tessellationFactor; + }; + + enum class PartitionMode + { + PartitionInteger, + PartitionFractionalEven, + PartitionFractionalOdd + }; + + std::unique_ptr m_states; + + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_hullShaderInteger; + Microsoft::WRL::ComPtr m_hullShaderFracEven; + Microsoft::WRL::ComPtr m_hullShaderFracOdd; + Microsoft::WRL::ComPtr m_domainShader; + Microsoft::WRL::ComPtr m_pixelShader; + Microsoft::WRL::ComPtr m_solidColorPS; + + Microsoft::WRL::ComPtr m_controlPointVB; // Control points for mesh + Microsoft::WRL::ComPtr m_cbPerFrame; + + Microsoft::WRL::ComPtr m_rasterizerStateSolid; + Microsoft::WRL::ComPtr m_rasterizerStateWireframe; + + //Control variables + float m_subdivs; + bool m_drawWires; + PartitionMode m_partitionMode; + + DirectX::XMFLOAT4X4 m_worldMatrix; + DirectX::XMFLOAT4X4 m_viewMatrix; + DirectX::XMFLOAT4X4 m_projectionMatrix; + DirectX::XMFLOAT3 m_cameraEye; + + std::unique_ptr m_help; + bool m_showHelp; +}; diff --git a/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.sln b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.sln new file mode 100644 index 0000000000000000000000000000000000000000..20387aad04948ad9a9a6058876de55f2cd55572b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleBezier", "SimpleBezier.vcxproj", "{3170784E-C580-45AA-8906-9C6CB30EDA9E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Debug|Durango.ActiveCfg = Debug|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Debug|Durango.Build.0 = Debug|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Debug|Durango.Deploy.0 = Debug|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Profile|Durango.ActiveCfg = Profile|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Profile|Durango.Build.0 = Profile|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Profile|Durango.Deploy.0 = Profile|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Release|Durango.ActiveCfg = Release|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Release|Durango.Build.0 = Release|Durango + {3170784E-C580-45AA-8906-9C6CB30EDA9E}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.vcxproj b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..c86018daaed9891c85dfb85c3241a6a02d6f3fa7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.vcxproj @@ -0,0 +1,309 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleBezier + {3170784e-c580-45aa-8906-9c6cb30eda9e} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + true + + + true + + + true + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + + + true + + + true + + + + + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierDS + Domain + BezierDS + Domain + BezierDS + Domain + + + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + + + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierPS + Pixel + BezierPS + Pixel + BezierPS + Pixel + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierVS + Vertex + BezierVS + Vertex + BezierVS + Vertex + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + SolidColorPS + Pixel + BezierPS + Pixel + BezierPS + Pixel + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..1afcd072fc628a58f54300bf82e3d4f55b7cc1f4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/SimpleBezier.vcxproj.filters @@ -0,0 +1,118 @@ + + + + + d381718a-6878-4819-9513-29c4c7537664 + + + 29ba2481-05be-4693-ae80-8eba3981d776 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {bf433f8a-2024-43bd-bfda-8d3804967a33} + + + {03b0bf25-c564-4293-94a4-3d194d170694} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + Shaders + + + + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier/StepTimer.h b/XDKSamples/IntroGraphics/SimpleBezier/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier/Telemetry.h b/XDKSamples/IntroGraphics/SimpleBezier/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleBezier/pch.cpp b/XDKSamples/IntroGraphics/SimpleBezier/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleBezier/pch.h b/XDKSamples/IntroGraphics/SimpleBezier/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..5f41518fa6b7cc4c2d9d5d988e6a917060ef29ca --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier/pch.h @@ -0,0 +1,64 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierDS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierDS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierDS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_fracEven.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_fracEven.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..7e4efff9b94634f47c3ac95bfd3eb347fb937f09 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_fracEven.hlsl @@ -0,0 +1,3 @@ +// Compiled with /D "BEZIER_HS_PARTITION=\\"fractional_even\\"" for fractional even partitioning. + +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_fracOdd.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_fracOdd.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..b66947fb54b5356458b542e19dd49774a8f201f1 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_fracOdd.hlsl @@ -0,0 +1,3 @@ +// Compiled with /D "BEZIER_HS_PARTITION=\\"fractional_odd\\"" for fractional odd partitioning. + +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_int.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_int.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..81b64e6afdaa3c4710d972ab110c63d71eb0e6b4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierHS_int.hlsl @@ -0,0 +1,3 @@ +// Compiled with /D "BEZIER_HS_PARTITION=\\"integer\\"" for integer partitioning. + +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierPS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierPS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierVS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/BezierVS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SimpleBezier.hlsli b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SimpleBezier.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..3d1abb8eccd3a5c9262e161584f279334957a4db --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SimpleBezier.hlsli @@ -0,0 +1,238 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.hlsli +// +// Shader demonstrating DirectX tessellation of a bezier surface +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +// The input patch size. In this sample, it is 16 control points. +// This value should match the call to IASetPrimitiveTopology() +#define INPUT_PATCH_SIZE 16 + +// The output patch size. In this sample, it is also 16 control points. +#define OUTPUT_PATCH_SIZE 16 + +// The root signature for the shaders. +#define rootSig "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), DescriptorTable(CBV(b0))" + + +//-------------------------------------------------------------------------------------- +// Constant Buffers +//-------------------------------------------------------------------------------------- +cbuffer cbPerFrame : register(b0) +{ + row_major matrix g_mViewProjection; + float3 g_cameraWorldPos; + float g_tessellationFactor; +}; + +//-------------------------------------------------------------------------------------- +// Vertex shader section +//-------------------------------------------------------------------------------------- +struct VS_CONTROL_POINT_INPUT +{ + float3 pos : POSITION; +}; + +struct VS_CONTROL_POINT_OUTPUT +{ + float3 pos : POSITION; +}; + +//-------------------------------------------------------------------------------------- +// This simple vertex shader passes the control points straight through to the +// hull shader. In a more complex scene, you might transform the control points +// or perform skinning at this step. +// +// The input to the vertex shader comes from the vertex buffer. +// +// The output from the vertex shader will go into the hull shader. +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +VS_CONTROL_POINT_OUTPUT BezierVS(VS_CONTROL_POINT_INPUT Input) +{ + VS_CONTROL_POINT_OUTPUT output; + + output.pos = Input.pos; + + return output; +} + +//-------------------------------------------------------------------------------------- +// Constant data function for the BezierHS. This is executed once per patch. +//-------------------------------------------------------------------------------------- +struct HS_CONSTANT_DATA_OUTPUT +{ + float Edges[4] : SV_TessFactor; + float Inside[2] : SV_InsideTessFactor; +}; + +struct HS_OUTPUT +{ + float3 pos : BEZIERPOS; +}; + +//-------------------------------------------------------------------------------------- +// This constant hull shader is executed once per patch. For the simple Mobius strip +// model, it will be executed 4 times. In this sample, we set the tessellation factor +// via SV_TessFactor and SV_InsideTessFactor for each patch. In a more complex scene, +// you might calculate a variable tessellation factor based on the camera's distance. +//-------------------------------------------------------------------------------------- +HS_CONSTANT_DATA_OUTPUT BezierConstantHS(InputPatch< VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE > ip, + uint PatchID : SV_PrimitiveID) +{ + HS_CONSTANT_DATA_OUTPUT output; + + float TessAmount = g_tessellationFactor; + + output.Edges[0] = output.Edges[1] = output.Edges[2] = output.Edges[3] = TessAmount; + output.Inside[0] = output.Inside[1] = TessAmount; + + return output; +} + +//-------------------------------------------------------------------------------------- +// BezierHS +// The hull shader is called once per output control point, which is specified with +// outputcontrolpoints. For this sample, we take the control points from the vertex +// shader and pass them directly off to the domain shader. In a more complex scene, +// you might perform a basis conversion from the input control points into a Bezier +// patch, such as the SubD11 SimpleBezier. +// +// The input to the hull shader comes from the vertex shader. +// +// The output from the hull shader will go to the domain shader. +// The tessellation factor, topology, and partition mode will go to the fixed function +// tessellator stage to calculate the UVW barycentric coordinates and domain points. +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +[domain("quad")] +[partitioning(BEZIER_HS_PARTITION)] +[outputtopology("triangle_cw")] +[outputcontrolpoints(OUTPUT_PATCH_SIZE)] +[patchconstantfunc("BezierConstantHS")] +HS_OUTPUT BezierHS(InputPatch< VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE > p, + uint i : SV_OutputControlPointID, + uint PatchID : SV_PrimitiveID) +{ + HS_OUTPUT output; + output.pos = p[i].pos; + return output; +} + +//-------------------------------------------------------------------------------------- +// Bezier evaluation domain shader section +//-------------------------------------------------------------------------------------- +struct DS_OUTPUT +{ + float4 pos : SV_POSITION; + float3 worldPos : WORLDPOS; + float3 normal : NORMAL; +}; + +//-------------------------------------------------------------------------------------- +float4 BernsteinBasis(float t) +{ + float invT = 1.0f - t; + + return float4(invT * invT * invT, + 3.0f * t * invT * invT, + 3.0f * t * t * invT, + t * t * t); +} + +//-------------------------------------------------------------------------------------- +float4 dBernsteinBasis(float t) +{ + float invT = 1.0f - t; + + return float4(-3 * invT * invT, + 3 * invT * invT - 6 * t * invT, + 6 * t * invT - 3 * t * t, + 3 * t * t); +} + +//-------------------------------------------------------------------------------------- +float3 EvaluateBezier(const OutputPatch< HS_OUTPUT, OUTPUT_PATCH_SIZE > BezPatch, + float4 BasisU, + float4 BasisV) +{ + float3 value = float3(0, 0, 0); + value = BasisV.x * (BezPatch[0].pos * BasisU.x + BezPatch[1].pos * BasisU.y + BezPatch[2].pos * BasisU.z + BezPatch[3].pos * BasisU.w); + value += BasisV.y * (BezPatch[4].pos * BasisU.x + BezPatch[5].pos * BasisU.y + BezPatch[6].pos * BasisU.z + BezPatch[7].pos * BasisU.w); + value += BasisV.z * (BezPatch[8].pos * BasisU.x + BezPatch[9].pos * BasisU.y + BezPatch[10].pos * BasisU.z + BezPatch[11].pos * BasisU.w); + value += BasisV.w * (BezPatch[12].pos * BasisU.x + BezPatch[13].pos * BasisU.y + BezPatch[14].pos * BasisU.z + BezPatch[15].pos * BasisU.w); + + return value; +} + + +//-------------------------------------------------------------------------------------- +// The domain shader is run once per vertex and calculates the final vertex's position +// and attributes. It receives the UVW from the fixed function tessellator and the +// control point outputs from the hull shader. Since we are using the DirectX 11 +// Tessellation pipeline, it is the domain shader's responsibility to calculate the +// final SV_POSITION for each vertex. In this sample, we evaluate the vertex's +// position using a Bernstein polynomial and the normal is calculated as the cross +// product of the U and V derivatives. +// +// The input SV_DomainLocation to the domain shader comes from fixed function +// tessellator. And the OutputPatch comes from the hull shader. From these, you +// must calculate the final vertex position, color, texcoords, and other attributes. +// +// The output from the domain shader will be a vertex that will go to the video card's +// rasterization pipeline and get drawn to the screen. +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +[domain("quad")] +DS_OUTPUT BezierDS(HS_CONSTANT_DATA_OUTPUT input, + float2 UV : SV_DomainLocation, + const OutputPatch< HS_OUTPUT, OUTPUT_PATCH_SIZE > BezPatch) +{ + float4 BasisU = BernsteinBasis(UV.x); + float4 BasisV = BernsteinBasis(UV.y); + float4 dBasisU = dBernsteinBasis(UV.x); + float4 dBasisV = dBernsteinBasis(UV.y); + + float3 worldPos = EvaluateBezier(BezPatch, BasisU, BasisV); + float3 tangent = EvaluateBezier(BezPatch, dBasisU, BasisV); + float3 biTangent = EvaluateBezier(BezPatch, BasisU, dBasisV); + float3 normal = normalize(cross(tangent, biTangent)); + + DS_OUTPUT output; + output.pos = mul(float4(worldPos, 1), g_mViewProjection); + output.worldPos = worldPos; + output.normal = normal; + + return output; +} + +//-------------------------------------------------------------------------------------- +// Smooth shading pixel shader section +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// The pixel shader works the same as it would in a normal graphics pipeline. +// In this sample, it performs very simple N dot L lighting. +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +float4 BezierPS(DS_OUTPUT Input) : SV_TARGET +{ + float3 N = normalize(Input.normal); + float3 L = normalize(Input.worldPos - g_cameraWorldPos); + return abs(dot(N, L)) * float4(1, 0, 0, 1); +} + +//-------------------------------------------------------------------------------------- +// Solid color shading pixel shader (used for wireframe overlay) +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +float4 SolidColorPS(DS_OUTPUT Input) : SV_TARGET +{ + // Return a dark green color + return float4(0, 0.25, 0, 1); +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SolidColorPS.hlsl b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SolidColorPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c65077845a509a493c769b4c85a72d2827e0bc15 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SolidColorPS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleBezier12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleBezier12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Main.cpp b/XDKSamples/IntroGraphics/SimpleBezier12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aae3a3307e6c2e2902bb260de83e81f2925d56a1 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleBezier.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleBezier12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..5ddacb4685dc7422253f63fbdb82b322cb06f100 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleBezier + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleBezier + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Readme.docx b/XDKSamples/IntroGraphics/SimpleBezier12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..06bc36ddb096bd94998393d2c5f8c0451c44cf79 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleBezier12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.cpp b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3da616001f04140c4e1c76e51d69e0d8618c0eb --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.cpp @@ -0,0 +1,519 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleBezier.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#pragma region Globals +// Global variables +namespace +{ + // Help menu text + const wchar_t* c_sampleTitle = L"Simple Bezier Sample"; + const wchar_t* c_sampleDescription = L"Demonstrates how to create hull and domain shaders to draw a\ntessellated Bezier surface representing a Mobius strip."; + const ATG::HelpButtonAssignment c_helpButtons[] = { + { ATG::HelpID::MENU_BUTTON, L"Show/Hide Help" }, + { ATG::HelpID::VIEW_BUTTON, L"Exit" }, + { ATG::HelpID::LEFT_STICK, L"Rotate Camera" }, + { ATG::HelpID::LEFT_TRIGGER, L"Decrease Subdivisions" }, + { ATG::HelpID::RIGHT_TRIGGER, L"Increase Subdivisions" }, + { ATG::HelpID::Y_BUTTON, L"Toggle Wireframe" }, + { ATG::HelpID::A_BUTTON, L"Fractional Partitioning (Even)" }, + { ATG::HelpID::B_BUTTON, L"Fractional Partitioning (Odd)" }, + { ATG::HelpID::X_BUTTON, L"Integer Partitioning" }, + }; + + // Min and max divisions of the patch per side for the slider control. + const float c_minDivs = 4.0f; + const float c_maxDivs = 16.0f; + // Startup subdivisions per side. + const float c_defaultSubdivs = 8.0f; + // Camera's rotation angle per step. + const float c_rotationAnglePerStep = XM_2PI / 360.0f; + + // Initial camera setup + const XMVECTORF32 c_cameraEye = { 0.0f, 0.45f, 2.7f, 0.0f }; + const XMVECTORF32 c_cameraAt = { 0.0f, 0.0f, 0.0f, 0.0f }; + const XMVECTORF32 c_cameraUp = { 0.0f, 1.0f, 0.0f, 0.0f }; + + // Draw the mesh with shaded triangles at start. + const bool c_defaultWireframeRendering = false; + + // Simple Bezier patch for a Mobius strip. + // 4 patches with 16 control points each. + const XMFLOAT3 c_mobiusStrip[64] = { + { 1.0f, -0.5f, 0.0f }, + { 1.0f, -0.5f, 0.5f }, + { 0.5f, -0.3536f, 1.354f }, + { 0.0f, -0.3536f, 1.354f }, + { 1.0f, -0.1667f, 0.0f }, + { 1.0f, -0.1667f, 0.5f }, + { 0.5f, -0.1179f, 1.118f }, + { 0.0f, -0.1179f, 1.118f }, + { 1.0f, 0.1667f, 0.0f }, + { 1.0f, 0.1667f, 0.5f }, + { 0.5f, 0.1179f, 0.8821f }, + { 0.0f, 0.1179f, 0.8821f }, + { 1.0f, 0.5f, 0.0f }, + { 1.0f, 0.5f, 0.5f }, + { 0.5f, 0.3536f, 0.6464f }, + { 0.0f, 0.3536f, 0.6464f }, + { 0.0f, -0.3536f, 1.354f }, + { -0.5f, -0.3536f, 1.354f }, + { -1.5f, 0.0f, 0.5f }, + { -1.5f, 0.0f, 0.0f }, + { 0.0f, -0.1179f, 1.118f }, + { -0.5f, -0.1179f, 1.118f }, + { -1.167f, 0.0f, 0.5f }, + { -1.167f, 0.0f, 0.0f }, + { 0.0f, 0.1179f, 0.8821f }, + { -0.5f, 0.1179f, 0.8821f }, + { -0.8333f, 0.0f, 0.5f }, + { -0.8333f, 0.0f, 0.0f }, + { 0.0f, 0.3536f, 0.6464f }, + { -0.5f, 0.3536f, 0.6464f }, + { -0.5f, 0.0f, 0.5f }, + { -0.5f, 0.0f, 0.0f }, + { -1.5f, 0.0f, 0.0f }, + { -1.5f, 0.0f, -0.5f }, + { -0.5f, 0.3536f, -1.354f }, + { 0.0f, 0.3536f, -1.354f }, + { -1.167f, 0.0f, 0.0f }, + { -1.167f, 0.0f, -0.5f }, + { -0.5f, 0.1179f, -1.118f }, + { 0.0f, 0.1179f, -1.118f }, + { -0.8333f, 0.0f, 0.0f }, + { -0.8333f, 0.0f, -0.5f }, + { -0.5f, -0.1179f, -0.8821f }, + { 0.0f, -0.1179f, -0.8821f }, + { -0.5f, 0.0f, 0.0f }, + { -0.5f, 0.0f, -0.5f }, + { -0.5f, -0.3536f, -0.6464f }, + { 0.0f, -0.3536f, -0.6464f }, + { 0.0f, 0.3536f, -1.354f }, + { 0.5f, 0.3536f, -1.354f }, + { 1.0f, 0.5f, -0.5f }, + { 1.0f, 0.5f, 0.0f }, + { 0.0f, 0.1179f, -1.118f }, + { 0.5f, 0.1179f, -1.118f }, + { 1.0f, 0.1667f, -0.5f }, + { 1.0f, 0.1667f, 0.0f }, + { 0.0f, -0.1179f, -0.8821f }, + { 0.5f, -0.1179f, -0.8821f }, + { 1.0f, -0.1667f, -0.5f }, + { 1.0f, -0.1667f, 0.0f }, + { 0.0f, -0.3536f, -0.6464f }, + { 0.5f, -0.3536f, -0.6464f }, + { 1.0f, -0.5f, -0.5f }, + { 1.0f, -0.5f, 0.0f }, + }; +} +#pragma endregion + +Sample::Sample() + : m_frame(0) + , m_subdivs(c_defaultSubdivs) + , m_drawWires(c_defaultWireframeRendering) + , m_partitionMode(PartitionMode::PartitionInteger) + , m_mappedConstantData(nullptr) + , m_showHelp(false) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); + + m_help = std::make_unique(c_sampleTitle, c_sampleDescription, c_helpButtons, _countof(c_helpButtons), true); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = !m_showHelp; + } + else if (m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + m_drawWires = !m_drawWires; + } + else if (m_gamePadButtons.x == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionInteger; + } + else if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionFractionalEven; + } + else if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + if (m_showHelp) + { + m_showHelp = false; + } + else + { + m_partitionMode = PartitionMode::PartitionFractionalOdd; + } + } + + if (pad.IsLeftTriggerPressed()) + { + m_subdivs = std::max(m_subdivs - 0.1f, c_minDivs); + } + + if (pad.IsRightTriggerPressed()) + { + m_subdivs = std::min(m_subdivs + 0.1f, c_maxDivs); + } + + if (pad.thumbSticks.leftX != 0.0f) + { + float rotationAxisY = -pad.thumbSticks.leftX * c_rotationAnglePerStep; + + XMVECTOR eye = XMLoadFloat3(&m_cameraEye); + eye = XMVector3Transform(eye, XMMatrixRotationY(rotationAxisY)); + XMMATRIX view = XMMatrixLookAtLH(eye, c_cameraAt, c_cameraUp); + XMStoreFloat4x4(&m_viewMatrix, view); + XMStoreFloat3(&m_cameraEye, eye); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + if (m_showHelp) + { + m_help->Render(commandList); + } + else + { + //Set appropriate pipeline state. + commandList->SetPipelineState(m_PSOs[m_drawWires ? 1 : 0][(int)m_partitionMode].Get()); + + // Set root signature and descriptor heaps. + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Calculate world-view-projection matrix. + XMMATRIX view = XMLoadFloat4x4(&m_viewMatrix); + XMMATRIX projection = XMLoadFloat4x4(&m_projectionMatrix); + XMMATRIX viewProjectionMatrix = XMMatrixMultiply(view, projection); + + // Update per-frame variables. + if (m_mappedConstantData != nullptr) + { + XMStoreFloat4x4(&m_mappedConstantData->viewProjectionMatrix, viewProjectionMatrix); + m_mappedConstantData->cameraWorldPos = m_cameraEye; + m_mappedConstantData->tessellationFactor = (float)m_subdivs; + } + + // Finalize dynamic constant buffer into descriptor heap. + commandList->SetGraphicsRootDescriptorTable(c_rootParameterCB, m_resourceDescriptors->GetGpuHandle(c_rootParameterCB)); + + commandList->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST); + commandList->IASetVertexBuffers(0, 1, &m_controlPointVBView); + + // Draw the mesh + commandList->DrawInstanced(_countof(c_mobiusStrip), 1, 0, 0); + } + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + // Use linear clear color for gamma-correct rendering. + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + CreateShaders(); + + // Initialize the world and view matrices. + XMMATRIX world = XMMatrixIdentity(); + XMMATRIX view = XMMatrixLookAtLH(c_cameraEye, c_cameraAt, c_cameraUp); + XMStoreFloat4x4(&m_worldMatrix, world); + XMStoreFloat4x4(&m_viewMatrix, view); + XMStoreFloat3(&m_cameraEye, c_cameraEye); + + RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + + ResourceUploadBatch uploadBatch(device); + uploadBatch.Begin(); + + m_help->RestoreDevice(device, uploadBatch, rtState); + + auto finish = uploadBatch.End(m_deviceResources->GetCommandQueue()); + finish.wait(); +} + +// Creates and initializes shaders and their data. +void Sample::CreateShaders() +{ + auto device = m_deviceResources->GetD3DDevice(); + + { + // Define root table layout. + CD3DX12_DESCRIPTOR_RANGE descRange[1]; + descRange[c_rootParameterCB].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); + CD3DX12_ROOT_PARAMETER rootParameters[1]; + rootParameters[c_rootParameterCB].InitAsDescriptorTable( + 1, &descRange[c_rootParameterCB], D3D12_SHADER_VISIBILITY_ALL); // b0 + + // Create the root signature. + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc(_countof(rootParameters), rootParameters, 0, nullptr, + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); + + ComPtr signature; + ComPtr error; + DX::ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create our vertex input layout. + const D3D12_INPUT_ELEMENT_DESC c_inputElementDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + // Load shaders. + auto vertexShaderBlob = DX::ReadData(L"BezierVS.cso"); + + std::vector hullShaderBlobs[c_numHullShaders]; + hullShaderBlobs[(int)PartitionMode::PartitionInteger] = DX::ReadData(L"BezierHS_int.cso"); + hullShaderBlobs[(int)PartitionMode::PartitionFractionalEven] = DX::ReadData(L"BezierHS_fracEven.cso"); + hullShaderBlobs[(int)PartitionMode::PartitionFractionalOdd] = DX::ReadData(L"BezierHS_fracOdd.cso"); + + auto domainShaderBlob = DX::ReadData(L"BezierDS.cso"); + + std::vector pixelShaderBlobs[c_numPixelShaders]; + pixelShaderBlobs[0] = DX::ReadData(L"BezierPS.cso"); + pixelShaderBlobs[1] = DX::ReadData(L"SolidColorPS.cso"); + + // Create solid and wireframe rasterizer state objects. + D3D12_RASTERIZER_DESC RasterDesc = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + RasterDesc.CullMode = D3D12_CULL_MODE_NONE; + RasterDesc.DepthClipEnable = TRUE; + + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout.pInputElementDescs = c_inputElementDesc; + psoDesc.InputLayout.NumElements = _countof(c_inputElementDesc); + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; + psoDesc.DS = { domainShaderBlob.data(), domainShaderBlob.size() }; + psoDesc.RasterizerState = RasterDesc; + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + + // Enumerate PSOs. + D3D12_FILL_MODE fillModes[] = { D3D12_FILL_MODE_SOLID, D3D12_FILL_MODE_WIREFRAME }; + for (uint8_t i = 0; i < c_numPixelShaders; i++) + { + psoDesc.RasterizerState.FillMode = fillModes[i]; + psoDesc.PS = { pixelShaderBlobs[i].data(), pixelShaderBlobs[i].size() }; + + for (uint8_t j = 0; j < c_numHullShaders; j++) + { + psoDesc.HS = { hullShaderBlobs[j].data(), hullShaderBlobs[j].size() }; + + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(m_PSOs[i][j].ReleaseAndGetAddressOf()))); + } + } + + { + // Create constant buffer. + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + + const D3D12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(ConstantBuffer)); + DX::ThrowIfFailed(device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, + &constantBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(m_cbPerFrame.GetAddressOf()))); + DX::ThrowIfFailed(m_cbPerFrame->SetName(L"Per Frame CB")); + + // Map it to a CPU variable. Leave the mapping active for per-frame updates. + DX::ThrowIfFailed(m_cbPerFrame->Map(0, nullptr, reinterpret_cast< void** >(&m_mappedConstantData))); + + // Create constant buffer view. + const uint32_t c_cbCount = 1; + m_resourceDescriptors = std::make_unique(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, c_cbCount); + + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = m_cbPerFrame->GetGPUVirtualAddress(); + cbvDesc.SizeInBytes = (sizeof(ConstantBuffer) + 255) & ~255; // CB size is required to be 256-byte aligned. + device->CreateConstantBufferView(&cbvDesc, m_resourceDescriptors->GetCpuHandle(c_rootParameterCB)); + + // Create vertex buffer containing a mesh's control points. + // Note: Using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are few verts to actually transfer. + const D3D12_RESOURCE_DESC vertexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(c_mobiusStrip)); + DX::ThrowIfFailed(device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, + &vertexBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(m_controlPointVB.GetAddressOf()))); + DX::ThrowIfFailed(m_controlPointVB->SetName(L"Control Point VB")); + + // Copy the MobiusStrip data to the vertex buffer. + uint8_t* dataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed(m_controlPointVB->Map( + 0, &readRange, reinterpret_cast(&dataBegin))); + memcpy(dataBegin, c_mobiusStrip, sizeof(c_mobiusStrip)); + m_controlPointVB->Unmap(0, nullptr); + + // Initialize vertex buffer view. + ZeroMemory(&m_controlPointVBView, sizeof(m_controlPointVBView)); + m_controlPointVBView.BufferLocation = m_controlPointVB->GetGPUVirtualAddress(); + m_controlPointVBView.StrideInBytes = sizeof(XMFLOAT3); + m_controlPointVBView.SizeInBytes = sizeof(c_mobiusStrip); + } + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + + XMMATRIX projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.01f, 100.0f); + XMStoreFloat4x4(&m_projectionMatrix, projection); + + m_help->SetWindow(size); +} +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.h b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.h new file mode 100644 index 0000000000000000000000000000000000000000..bab5e8e63626d9d8f51a18a12b9beda1dcf985cc --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.h @@ -0,0 +1,102 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "ControllerHelp.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateShaders(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Sample objects + struct ConstantBuffer + { + DirectX::XMFLOAT4X4 viewProjectionMatrix; + DirectX::XMFLOAT3 cameraWorldPos; + float tessellationFactor; + }; + + enum class PartitionMode + { + PartitionInteger, + PartitionFractionalEven, + PartitionFractionalOdd + }; + + static const size_t c_numPixelShaders = 2; + static const size_t c_numHullShaders = 3; + + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_PSOs[c_numPixelShaders][c_numHullShaders]; + + std::unique_ptr m_resourceDescriptors; + + D3D12_VERTEX_BUFFER_VIEW m_controlPointVBView; + Microsoft::WRL::ComPtr m_controlPointVB; // Control points for mesh + Microsoft::WRL::ComPtr m_cbPerFrame; + ConstantBuffer* m_mappedConstantData; + + // Index in the root parameter table + static const UINT c_rootParameterCB = 0; + + // Control variables + float m_subdivs; + bool m_drawWires; + PartitionMode m_partitionMode; + + DirectX::XMFLOAT4X4 m_worldMatrix; + DirectX::XMFLOAT4X4 m_viewMatrix; + DirectX::XMFLOAT4X4 m_projectionMatrix; + DirectX::XMFLOAT3 m_cameraEye; + + std::unique_ptr m_help; + bool m_showHelp; +}; diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.sln b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.sln new file mode 100644 index 0000000000000000000000000000000000000000..376d7778ecbd1c1db898d874d605768b7472f439 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleBezier", "SimpleBezier.vcxproj", "{CF98331B-A991-431E-A43B-3487A2919DA6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CF98331B-A991-431E-A43B-3487A2919DA6}.Debug|Durango.ActiveCfg = Debug|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Debug|Durango.Build.0 = Debug|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Debug|Durango.Deploy.0 = Debug|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Profile|Durango.ActiveCfg = Profile|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Profile|Durango.Build.0 = Profile|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Profile|Durango.Deploy.0 = Profile|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Release|Durango.ActiveCfg = Release|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Release|Durango.Build.0 = Release|Durango + {CF98331B-A991-431E-A43B-3487A2919DA6}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.vcxproj b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..78ee54e64ae5afaa8fe34e4b64bea052a9893581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.vcxproj @@ -0,0 +1,324 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleBezier + {cf98331b-a991-431e-a43b-3487a2919da6} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierDS + BezierDS + BezierDS + Domain + Domain + Domain + 5.0 + 5.0 + 5.0 + + + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + 5.0 + 5.0 + 5.0 + + + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + 5.0 + 5.0 + 5.0 + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + 5.0 + 5.0 + 5.0 + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + Pixel + Pixel + Pixel + BezierPS + BezierPS + BezierPS + 5.0 + 5.0 + 5.0 + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierVS + Vertex + BezierVS + Vertex + BezierVS + Vertex + 5.0 + 5.0 + 5.0 + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + Pixel + Pixel + Pixel + SolidColorPS + SolidColorPS + SolidColorPS + 5.0 + 5.0 + 5.0 + + + + + true + + + true + + + true + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..cb39ef070046f2417cc0c12bc38391821f9366a9 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/SimpleBezier.vcxproj.filters @@ -0,0 +1,118 @@ + + + + + bab48f42-2b02-4de5-a23f-c865ebadac6d + + + 135e4243-0a72-444c-9bde-1170dc9b5e49 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {e70ef754-acf3-4d54-b647-914e76450e68} + + + {fdc4252a-d307-4ce6-bc74-09fb60e22dcb} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + + + Shaders + + + + Assets + + + Assets + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleBezier12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleBezier12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/pch.cpp b/XDKSamples/IntroGraphics/SimpleBezier12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleBezier12/pch.h b/XDKSamples/IntroGraphics/SimpleBezier12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..2a13999b3cc26c513c90a52103fd3aec1a7ac65f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleBezier12/pch.h @@ -0,0 +1,65 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "DirectXHelpers.h" +#include "DescriptorHeap.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleCompute/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleCompute/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleCompute/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleCompute/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleCompute/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Assets/fractal.hlsl b/XDKSamples/IntroGraphics/SimpleCompute/Assets/fractal.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c843bce50d780f304e33cd2c8e74e84e1251e5a3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/Assets/fractal.hlsl @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------------------- +// File: fractal.hlsl +// +// This is a compute shader that draws a Mandelbrot fractal. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +RWTexture2D OutputTexture : register(u0); +Texture2D ColorMapTexture : register(t0); +SamplerState ColorMapSampler : register(s0); + +cbuffer cb0 +{ + float4 g_MaxThreadIter : packoffset(c0); + float4 g_Window : packoffset(c1); +} + +[numthreads(8, 8, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + float2 WindowLocal = ((float2)DTid.xy / g_MaxThreadIter.xy) * float2(1, -1) + float2(-0.5f, 0.5f); + float2 coord = WindowLocal.xy * g_Window.xy + g_Window.zw; + + uint maxiter = (uint)g_MaxThreadIter.z * 4; + uint iter = 0; + float2 constant = coord; + float2 sq; + do + { + float2 newvalue; + sq = coord * coord; + newvalue.x = sq.x - sq.y; + newvalue.y = 2 * coord.y * coord.x; + coord = newvalue + constant; + iter++; + } while (iter < maxiter && (sq.x + sq.y) < 4.0); + + float colorIndex = frac((float)iter / g_MaxThreadIter.z); + float4 SampledColor = ColorMapTexture.SampleLevel(ColorMapSampler, float2(colorIndex, 0), 0); + + OutputTexture[DTid.xy] = SampledColor; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleCompute/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8deeb0a5c8fb1df063fd37d2c701c133fe421b3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/DeviceResources.cpp @@ -0,0 +1,222 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{ 0, 0, 1920, 1080 }, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = { nullptr }; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(0, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleCompute/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..3c3c15cb9fe500e5230d0019bc95015f2789f94b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/DeviceResources.h @@ -0,0 +1,70 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Main.cpp b/XDKSamples/IntroGraphics/SimpleCompute/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5f050843ed7445e63e080bad61289423b93874b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleCompute.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleCompute/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..d7cecad195bb7d95c2968bfbb5072ad4b6723f88 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleCompute + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleCompute + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Readme.docx b/XDKSamples/IntroGraphics/SimpleCompute/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..5070b93a0eb51ba9d7df9f1795b35299796d7842 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.cpp b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71b3ca28c42fc8fe82798c4fcf75a3582a930193 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.cpp @@ -0,0 +1,483 @@ +//-------------------------------------------------------------------------------------- +// SimpleCompute.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleCompute.h" + +#include "ATGColors.h" +#include "ControllerFont.h" +#include "ReadData.h" + +#define USE_FAST_SEMANTICS + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + const uint32_t s_numShaderThreads = 8; // make sure to update value in shader if this changes + + const wchar_t* g_SampleTitle = L"SimpleCompute"; + const wchar_t* g_SampleDescription = L"Demonstrates how to use the ID3D11ComputeContextX interface to submit asynchronous compute shader workloads"; + const ATG::HelpButtonAssignment g_HelpButtons[] = { + { ATG::HelpID::MENU_BUTTON, L"Show/Hide Help" }, + { ATG::HelpID::VIEW_BUTTON, L"Exit" }, + { ATG::HelpID::LEFT_STICK, L"Pan Viewport" }, + { ATG::HelpID::RIGHT_STICK, L"Zoom Viewport" }, + { ATG::HelpID::RIGHT_TRIGGER, L"Increase Zoom Speed" }, + { ATG::HelpID::A_BUTTON, L"Toggle Async Compute" }, + { ATG::HelpID::Y_BUTTON, L"Reset Viewport to Default" }, + }; +} + +Sample::Sample() : + m_frame(0) + , m_showHelp(false) + , m_usingAsyncCompute(false) + , m_requestUsingAsyncCompute(false) + , m_asyncComputeActive(false) + , m_renderIndex(0) + , m_terminateThread(false) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, 2 +#ifdef USE_FAST_SEMANTICS + , DX::DeviceResources::c_FastSemantics +#endif + ); + + + m_help = std::make_unique(g_SampleTitle, g_SampleDescription, g_HelpButtons, _countof(g_HelpButtons)); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + ResetWindow(); + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_computeThread = new std::thread(&Sample::AsyncComputeThreadProc, this); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + m_renderFPS.Tick(elapsedTime); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = !m_showHelp; + } + else if (m_showHelp && m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = false; + } + + if (!m_showHelp) + { + if (pad.IsViewPressed()) + { + ExitSample(); + } + + if (m_gamePadButtons.a == DirectX::GamePad::ButtonStateTracker::PRESSED) + { + m_requestUsingAsyncCompute = !m_requestUsingAsyncCompute; + + if (!m_requestUsingAsyncCompute && m_usingAsyncCompute) + { + m_usingAsyncCompute = false; + // wait for async compute to finish current iteration + while (m_asyncComputeActive) + { + SwitchToThread(); + } + } + else if (m_requestUsingAsyncCompute && !m_usingAsyncCompute) + { + m_usingAsyncCompute = true; + } + } + const float ThumbLeftX = pad.thumbSticks.leftX; + const float ThumbLeftY = pad.thumbSticks.leftY; + const float ThumbRightY = pad.thumbSticks.rightY; + const float RightTrigger = m_gamePadButtons.rightTrigger == DirectX::GamePad::ButtonStateTracker::HELD; + + if (m_gamePadButtons.y == DirectX::GamePad::ButtonStateTracker::PRESSED) + { + ResetWindow(); + } + + if (ThumbLeftX != 0.0f || ThumbLeftY != 0.0f || ThumbRightY != 0.0f) + { + const float ScaleSpeed = 1.0f + RightTrigger * 4.0f; + const float WindowScale = 1.0f + ThumbRightY * -0.25f * ScaleSpeed * elapsedTime; + m_window.x *= WindowScale; + m_window.y *= WindowScale; + m_window.z += m_window.x * ThumbLeftX * elapsedTime * 0.5f; + m_window.w += m_window.y * ThumbLeftY * elapsedTime * 0.5f; + m_windowUpdated = true; + } + if (!m_usingAsyncCompute) + { + m_windowUpdated = true; + } + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + + if (m_showHelp) + { + m_help->Render(); + } + else + { + // Flip colors for which async compute buffer is being rendered + PIXBeginEvent(context, m_renderIndex ? PIX_COLOR(0, 0, 255) : PIX_COLOR(0,255,0), L"Render"); + + if (!m_usingAsyncCompute) + { + D3D11_TEXTURE2D_DESC TexDesc = {}; + m_fractalTexture[0]->GetDesc(&TexDesc); + + const uint32_t frameIndex = m_timer.GetFrameCount(); + const uint32_t bufferIndex = frameIndex % 2; + CB_FractalCS* cbData = &m_cbFractalData[bufferIndex]; + cbData->MaxThreadIter = XMFLOAT4((float)TexDesc.Width, (float)TexDesc.Height, (float)m_fractalMaxIterations, 0); + + cbData->Window = m_window; + context->CSSetPlacementConstantBuffer(0, m_cbFractal.Get(), cbData); + context->CSSetShaderResources(0, 1, m_fractalColorMapSRV[0].GetAddressOf()); + context->CSSetSamplers(0, 1, m_fractalBilinearSampler.GetAddressOf()); + context->CSSetShader(m_csFractal.Get(), nullptr, 0); + context->CSSetUnorderedAccessViews(0, 1, m_fractalUAV[m_renderIndex].GetAddressOf(), nullptr); + + const uint32_t threadGroupX = TexDesc.Width / s_numShaderThreads; + const uint32_t threadGroupY = TexDesc.Height / s_numShaderThreads; + context->Dispatch(threadGroupX, threadGroupY, 1); + +#ifdef USE_FAST_SEMANTICS + context->GpuSendPipelinedEvent(D3D11X_GPU_PIPELINED_EVENT_CS_PARTIAL_FLUSH); +#endif + } + else + { + while (!m_asyncComputeActive) + { + SwitchToThread(); + } + } + RECT outputSize = m_deviceResources->GetOutputSize(); + + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(outputSize.right, outputSize.bottom); + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_fractalSRV[m_renderIndex].Get(), outputSize); + + wchar_t outputString[256] = {}; + swprintf_s(outputString, 256, L"Simple Compute Context %0.2f fps", m_renderFPS.GetFPS()); + + m_font->DrawString(m_spriteBatch.get(), outputString, pos); + pos.y += m_font->GetLineSpacing(); + if (m_usingAsyncCompute) + { + swprintf_s(outputString, 256, L"Asynchronous compute %0.2f fps GPU time: %0.3f msec", m_computeFPS.GetFPS(), m_lastAsyncExecuteTimeMsec); + m_font->DrawString(m_spriteBatch.get(), outputString, pos); + } + else + { + swprintf_s(outputString, 256, L"Synchronous compute %0.2f fps", m_renderFPS.GetFPS()); + m_font->DrawString(m_spriteBatch.get(), outputString, pos); + } + + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), + L"[A] Toggle asynchronous vs. synchronous [View] Exit [Menu] Help", + XMFLOAT2(float(safeRect.left), float(safeRect.bottom) - m_font->GetLineSpacing())); + + m_spriteBatch->End(); + + PIXEndEvent(context); + } + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + D3D11_COMPUTE_CONTEXT_DESC CCDesc = {}; + DX::ThrowIfFailed( + device->CreateComputeContextX(&CCDesc, m_computeContext.ReleaseAndGetAddressOf())); + + auto blob = DX::ReadData(L"Fractal.cso"); + DX::ThrowIfFailed( + device->CreateComputeShader(blob.data(), blob.size(), nullptr, m_csFractal.ReleaseAndGetAddressOf())); + + RECT outputSize = m_deviceResources->GetOutputSize(); + CD3D11_TEXTURE2D_DESC TexDesc( + DXGI_FORMAT_R8G8B8A8_UNORM, + outputSize.right, + outputSize.bottom, + 1, + 1, + D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE + ); + + DX::ThrowIfFailed( + device->CreateTexture2D(&TexDesc, nullptr, m_fractalTexture[0].ReleaseAndGetAddressOf())); + + DX::ThrowIfFailed( + device->CreateShaderResourceView(m_fractalTexture[0].Get(), nullptr, m_fractalSRV[0].ReleaseAndGetAddressOf())); + + CD3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc(D3D11_UAV_DIMENSION_TEXTURE2D, TexDesc.Format); + DX::ThrowIfFailed( + device->CreateUnorderedAccessView(m_fractalTexture[0].Get(), &UAVDesc, m_fractalUAV[0].ReleaseAndGetAddressOf())); + + DX::ThrowIfFailed( + device->CreateTexture2D(&TexDesc, nullptr, m_fractalTexture[1].ReleaseAndGetAddressOf())); + + DX::ThrowIfFailed( + device->CreateShaderResourceView(m_fractalTexture[1].Get(), nullptr, m_fractalSRV[1].ReleaseAndGetAddressOf())); + + DX::ThrowIfFailed( + device->CreateUnorderedAccessView(m_fractalTexture[1].Get(), &UAVDesc, m_fractalUAV[1].ReleaseAndGetAddressOf())); + + m_cbFractalData = (CB_FractalCS*)VirtualAlloc(nullptr, 2 * sizeof(CB_FractalCS), MEM_GRAPHICS | MEM_LARGE_PAGES | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GPU_COHERENT); + CD3D11_BUFFER_DESC BufDesc(sizeof(CB_FractalCS), D3D11_BIND_CONSTANT_BUFFER); + DX::ThrowIfFailed( + device->CreatePlacementBuffer(&BufDesc, m_cbFractalData, m_cbFractal.GetAddressOf())); + + m_fractalTimestamps = (uint64_t*)VirtualAlloc(nullptr, 64 * 1024, MEM_GRAPHICS | MEM_LARGE_PAGES | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_GPU_COHERENT); + + TexDesc.Width = 8; + TexDesc.Height = 1; + TexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + const uint32_t RainbowTexels[8] = { 0xFF0000FF, 0xFF0080FF, 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000, 0xFF800000, 0xFFFF00FF }; + const uint32_t GradientTexels[8] = { 0xFF000040, 0xFF000080, 0xFF0000C0, 0xFF0000FF, 0xFF0040FF, 0xFF0080FF, 0xFF00C0FF, 0xFF00FFFF }; + static_assert(sizeof(RainbowTexels) == sizeof(GradientTexels), "Mismatched size"); + + D3D11_SUBRESOURCE_DATA InitData = {}; + InitData.SysMemPitch = sizeof(GradientTexels); + InitData.pSysMem = GradientTexels; + DX::ThrowIfFailed( + device->CreateTexture2D(&TexDesc, &InitData, m_fractalColorMap[0].ReleaseAndGetAddressOf())); + + InitData.pSysMem = RainbowTexels; + DX::ThrowIfFailed( + device->CreateTexture2D(&TexDesc, &InitData, m_fractalColorMap[1].ReleaseAndGetAddressOf())); + + DX::ThrowIfFailed( + device->CreateShaderResourceView(m_fractalColorMap[0].Get(), nullptr, m_fractalColorMapSRV[0].ReleaseAndGetAddressOf())); + DX::ThrowIfFailed( + device->CreateShaderResourceView(m_fractalColorMap[1].Get(), nullptr, m_fractalColorMapSRV[1].ReleaseAndGetAddressOf())); + + CD3D11_SAMPLER_DESC SamplerDesc(D3D11_DEFAULT); + SamplerDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + DX::ThrowIfFailed( + device->CreateSamplerState(&SamplerDesc, m_fractalBilinearSampler.ReleaseAndGetAddressOf())); + + m_fractalMaxIterations = 300; + + m_spriteBatch = std::make_unique(context); + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneControllerLegendSmall.spritefont"); + m_help->RestoreDevice(context); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + m_help->SetWindow(size); + + m_spriteBatch->SetViewport(m_deviceResources->GetScreenViewport()); +} +#pragma endregion + +void Sample::ResetWindow() +{ + m_window = XMFLOAT4(4.0f, 2.25f, -0.65f, 0.0f); + m_windowUpdated = true; +} + +void Sample::AsyncComputeThreadProc() +{ + LARGE_INTEGER PerfFreq; + QueryPerformanceFrequency(&PerfFreq); + + LARGE_INTEGER LastFrameTime; + QueryPerformanceCounter(&LastFrameTime); + + D3D11_TEXTURE2D_DESC TexDesc = {}; + m_fractalTexture[0]->GetDesc(&TexDesc); + const uint32_t ThreadGroupX = TexDesc.Width / s_numShaderThreads; + const uint32_t ThreadGroupY = TexDesc.Height / s_numShaderThreads; + CB_FractalCS* pCBData = &m_cbFractalData[0]; + pCBData->MaxThreadIter = XMFLOAT4((float)TexDesc.Width, (float)TexDesc.Height, (float)m_fractalMaxIterations, 0); + + auto device = m_deviceResources->GetD3DDevice(); + + while (!m_terminateThread) + { + LARGE_INTEGER CurrentFrameTime; + QueryPerformanceCounter(&CurrentFrameTime); + double DeltaTime = (double)(CurrentFrameTime.QuadPart - LastFrameTime.QuadPart) / (double)PerfFreq.QuadPart; + LastFrameTime = CurrentFrameTime; + + if (m_usingAsyncCompute) + { + if (m_windowUpdated) + { + m_computeFPS.Tick((float)DeltaTime); + + pCBData->Window = m_window; + PIXBeginEvent(m_computeContext.Get(), !m_renderIndex ? PIX_COLOR(0, 0, 255) : PIX_COLOR(0, 255, 0), "Compute"); + m_computeContext->FlushGpuCachesTopOfPipe(0); + m_computeContext->CSSetPlacementConstantBuffer(0, m_cbFractal.Get(), pCBData); + m_computeContext->CSSetShaderResources(0, 1, m_fractalColorMapSRV[1].GetAddressOf()); + m_computeContext->CSSetSamplers(0, 1, m_fractalBilinearSampler.GetAddressOf()); + m_computeContext->CSSetShader(m_csFractal.Get(), nullptr, 0); + m_computeContext->CSSetUnorderedAccessViews(0, 1, m_fractalUAV[1 - m_renderIndex].GetAddressOf(), nullptr); + m_computeContext->WriteTimestampToMemory(&m_fractalTimestamps[0]); + m_computeContext->Dispatch(ThreadGroupX, ThreadGroupY, 1); + m_computeContext->WriteTimestampToMemory(&m_fractalTimestamps[1]); + PIXEndEvent(m_computeContext.Get()); + + uint64_t fence = m_computeContext->InsertFence(0); + while (device->IsFencePending(fence)) + { + SwitchToThread(); + } + m_renderIndex = 1 - m_renderIndex; + + uint64_t GpuTicks = m_fractalTimestamps[1] - m_fractalTimestamps[0]; + double GpuMsec = (double)GpuTicks * 1e-5; + m_lastAsyncExecuteTimeMsec = (float)GpuMsec; + + m_asyncComputeActive = true; + } + else + { + SwitchToThread(); + } + } + else + { + m_asyncComputeActive = false; + SwitchToThread(); + } + } + m_asyncComputeActive = false; +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.h b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.h new file mode 100644 index 0000000000000000000000000000000000000000..31bd8eee04b89853284945eb652be52dc2f795e5 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.h @@ -0,0 +1,138 @@ +//-------------------------------------------------------------------------------------- +// SimpleCompute.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "ControllerHelp.h" + +class SmoothedFPS +{ +public: + SmoothedFPS(uint32_t frameInterval = 100) + { + Initialize(frameInterval); + } + + void Initialize(uint32_t frameInterval = 100) + { + m_frameInterval = frameInterval; + m_timeAccumulator = 0.0f; + m_frameAccumulator = 0; + m_smoothedFPS = 0.0f; + } + + void Tick(float DeltaTime) + { + m_timeAccumulator += DeltaTime; + ++m_frameAccumulator; + + if (m_frameAccumulator >= m_frameInterval) + { + m_smoothedFPS = (float)m_frameInterval / m_timeAccumulator; + m_timeAccumulator = 0.0f; + m_frameAccumulator = 0; + } + } + + float GetFPS() const { return m_smoothedFPS; } + +private: + float m_smoothedFPS; + float m_timeAccumulator; + uint32_t m_frameAccumulator; + uint32_t m_frameInterval; + +}; + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + struct CB_FractalCS + { + DirectX::XMFLOAT4 MaxThreadIter; + DirectX::XMFLOAT4 Window; + }; + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void ResetWindow(); + void AsyncComputeThreadProc(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + std::unique_ptr m_help; + bool m_showHelp; + + // Input devices. + std::unique_ptr m_gamePad; + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // Compute data + SmoothedFPS m_renderFPS; + SmoothedFPS m_computeFPS; + + std::atomic m_terminateThread; + std::thread * m_computeThread; + + CB_FractalCS* m_cbFractalData; + UINT m_renderIndex; + uint64_t* m_fractalTimestamps; + DirectX::XMFLOAT4 m_window; + std::atomic m_windowUpdated; + uint32_t m_asyncExecuteCount; + float m_lastAsyncExecuteTimeMsec; + uint32_t m_fractalMaxIterations; + + Microsoft::WRL::ComPtr m_cbFractal; + Microsoft::WRL::ComPtr m_csFractal; + Microsoft::WRL::ComPtr m_fractalTexture[2]; + Microsoft::WRL::ComPtr m_fractalUAV[2]; + Microsoft::WRL::ComPtr m_fractalSRV[2]; + Microsoft::WRL::ComPtr m_computeContext; + Microsoft::WRL::ComPtr m_fractalColorMap[2]; + Microsoft::WRL::ComPtr m_fractalColorMapSRV[2]; + Microsoft::WRL::ComPtr m_fractalBilinearSampler; + + std::atomic m_usingAsyncCompute; + bool m_requestUsingAsyncCompute; + std::atomic m_asyncComputeActive; + + // DirectXTK objects. + std::unique_ptr m_spriteBatch; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; +}; diff --git a/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.sln b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.sln new file mode 100644 index 0000000000000000000000000000000000000000..9b55b001d917aaab7afa248124f953956f38d848 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleCompute", "SimpleCompute.vcxproj", "{CE342843-AA5E-4D58-A46D-4CEBA9807B30}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Debug|Durango.ActiveCfg = Debug|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Debug|Durango.Build.0 = Debug|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Debug|Durango.Deploy.0 = Debug|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Profile|Durango.ActiveCfg = Profile|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Profile|Durango.Build.0 = Profile|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Profile|Durango.Deploy.0 = Profile|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Release|Durango.ActiveCfg = Release|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Release|Durango.Build.0 = Release|Durango + {CE342843-AA5E-4D58-A46D-4CEBA9807B30}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.vcxproj b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..c96daa2eb3047dfb2eed62f27b137955e384cb1f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.vcxproj @@ -0,0 +1,246 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleCompute + {ce342843-aa5e-4d58-a46d-4ceba9807b30} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + Compute + Compute + Compute + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..05bef91d4a4edb0d72007e047625618c9f20699d --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/SimpleCompute.vcxproj.filters @@ -0,0 +1,100 @@ + + + + + 911861b5-a8f3-4364-8a19-757552990b3e + + + 18558648-3ad7-478e-b8a5-20d6bcf4cf37 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 8a9c09a9-f629-40a3-9ea5-99a6eff8ce72 + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + + Assets + + + Assets + + + Assets + + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute/StepTimer.h b/XDKSamples/IntroGraphics/SimpleCompute/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..1a7ca7057c2fb7cb6ab25c6c586efb1cbce994b3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception("QueryPerformanceFrequency"); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute/Telemetry.h b/XDKSamples/IntroGraphics/SimpleCompute/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..1cc79649c08adb1beec35034b48e68a31149e69b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/Telemetry.h @@ -0,0 +1,91 @@ +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + // Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below + // + EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = { {EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0} }; + + // Event name mapping + // +#define SampleLoaded_value 1 + +// Event Descriptor array +// + EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault } }; + + // Provider Descriptor for ATGSampleTelemetry + // + EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = { "ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal }; + + // ETW handle for ATGSampleTelemetry + // + EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + + /*++ + + Routine Description: + + Register the provider with ETW+. + + Arguments: + + None + + Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + + --*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + + /*++ + + Routine Description: + + Unregister the provider from ETW+. + + Arguments: + None + Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. + --*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + + // Entry point to log the event SampleLoaded + // + __inline + ULONG + EventWriteSampleLoaded(__in_opt PCWSTR ExeName) + { +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); + } +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleCompute/pch.cpp b/XDKSamples/IntroGraphics/SimpleCompute/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleCompute/pch.h b/XDKSamples/IntroGraphics/SimpleCompute/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..2062d94c5d05fd8401803bf14f92b019250918ef --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute/pch.h @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A04AA /* XDK Edition: 160300 */ +#error This sample requires the March 2016 XDK or later +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Assets/fractal.hlsl b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/fractal.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..568898bf43e85a0f2e7c0083063842463790355f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/Assets/fractal.hlsl @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------------------------- +// File: fractal.hlsl +// +// This is a compute shader that draws a Mandelbrot fractal. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#define RS\ +[\ + RootSignature\ + (\ + "CBV(b0, visibility=SHADER_VISIBILITY_ALL),\ + DescriptorTable(Sampler(s0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL),\ + DescriptorTable(SRV(t0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL),\ + DescriptorTable(UAV(u0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)"\ + )\ +] + +RWTexture2D OutputTexture : register(u0); +Texture2D ColorMapTexture : register(t0); +SamplerState ColorMapSampler : register(s0); + +cbuffer cb0 +{ + float4 g_MaxThreadIter : packoffset(c0); + float4 g_Window : packoffset(c1); +} + +[numthreads(8, 8, 1)] +RS +void main(uint3 DTid : SV_DispatchThreadID) +{ + float2 WindowLocal = ((float2)DTid.xy / g_MaxThreadIter.xy) * float2(1, -1) + float2(-0.5f, 0.5f); + float2 coord = WindowLocal.xy * g_Window.xy + g_Window.zw; + + uint maxiter = (uint)g_MaxThreadIter.z * 4; + uint iter = 0; + float2 constant = coord; + float2 sq; + do + { + float2 newvalue; + sq = coord * coord; + newvalue.x = sq.x - sq.y; + newvalue.y = 2 * coord.y * coord.x; + coord = newvalue + constant; + iter++; + } while (iter < maxiter && (sq.x + sq.y) < 4.0); + + float colorIndex = frac((float)iter / g_MaxThreadIter.z); + float4 SampledColor = ColorMapTexture.SampleLevel(ColorMapSampler, float2(colorIndex, 0), 0); + + OutputTexture[DTid.xy] = SampledColor; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleCompute12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b59af2ad03e61204607639e97b5f33e6da3a5f9 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/DeviceResources.cpp @@ -0,0 +1,459 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{ 0, 0, 1920, 1080 }, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = (m_options & c_EnableHDR) ? (m_backBufferCount * 2) : m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_renderTargetsGameDVR[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + + if (m_swapChainGameDVR) + { + DX::ThrowIfFailed(m_swapChainGameDVR->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargetsGameDVR[n].GetAddressOf()))); + + swprintf_s(name, L"GameDVR Render target %u", n); + m_renderTargetsGameDVR[n]->SetName(name); + + rtvDesc.Format = m_gameDVRFormat; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptorGameDVR(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferCount + n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargetsGameDVR[n].Get(), &rtvDesc, rtvDescriptorGameDVR); + } + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + if (m_options & c_EnableHDR) + { + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET), + }; + m_commandList->ResourceBarrier(_countof(barriers), barriers); + } + else + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + if (m_options & c_EnableHDR) + { + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), + CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargetsGameDVR[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT), + }; + m_commandList->ResourceBarrier(_countof(barriers), barriers); + } + else + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(0, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleCompute12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4233f622b36ee0a25f19008392290195813eb63 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/DeviceResources.h @@ -0,0 +1,116 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + static const unsigned int c_EnableHDR = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D12Resource* GetGameDVRRenderTarget() const { return m_renderTargetsGameDVR[m_backBufferIndex].Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetGameDVRRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferCount + m_backBufferIndex, m_rtvDescriptorSize); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_renderTargetsGameDVR[MAX_BACK_BUFFER_COUNT]; + DXGI_FORMAT m_gameDVRFormat; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Main.cpp b/XDKSamples/IntroGraphics/SimpleCompute12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8f1ef1941ec79d871b6f6a75e26726151a806d5 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/Main.cpp @@ -0,0 +1,174 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleCompute12.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +bool g_HDRMode = false; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + if (m_sample->RequestHDRMode()) + { + // Request HDR mode. + auto determineHDR = Concurrency::create_task( + Windows::Xbox::Graphics::Display::DisplayConfiguration::TrySetHdrModeAsync() + ); + + // In a real game, you'd do some initialization here to hide the HDR mode switch. + + // Finish up HDR mode detection (waiting for async if needed) + g_HDRMode = determineHDR.get()->HdrEnabled; + + #ifdef _DEBUG + OutputDebugStringA((g_HDRMode) ? "INFO: Display in HDR Mode\n" : "INFO: Display in SDR Mode\n"); + #endif + } + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleCompute12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..ba77b07d8cca0bf6f6ad87cf396f36ebc02657a7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleCompute12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleCompute12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Readme.docx b/XDKSamples/IntroGraphics/SimpleCompute12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..2218ff703f7138e695698160c29847f020600862 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleCompute12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.cpp b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab8a92eed020ba041512b523db255e8b0bdffeab --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.cpp @@ -0,0 +1,764 @@ +//-------------------------------------------------------------------------------------- +// SimpleCompute12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleCompute12.h" + +#include "ATGColors.h" +#include "ControllerFont.h" +#include "ReadData.h" + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + const uint32_t s_numShaderThreads = 8; // make sure to update value in shader if this changes + + const wchar_t* g_SampleTitle = L"SimpleCompute12"; + const wchar_t* g_SampleDescription = L"Demonstrates how to use the D3D12_COMMAND_LIST_TYPE_COMPUTE interface to submit asynchronous compute shader workloads"; + const ATG::HelpButtonAssignment g_HelpButtons[] = { + { ATG::HelpID::MENU_BUTTON, L"Show/Hide Help" }, + { ATG::HelpID::VIEW_BUTTON, L"Exit" }, + { ATG::HelpID::LEFT_STICK, L"Pan Viewport" }, + { ATG::HelpID::RIGHT_STICK, L"Zoom Viewport" }, + { ATG::HelpID::RIGHT_TRIGGER, L"Increase Zoom Speed" }, + { ATG::HelpID::A_BUTTON, L"Toggle Async Compute" }, + { ATG::HelpID::Y_BUTTON, L"Reset Viewport to Default" }, + }; + + const D3D12_SAMPLER_DESC s_samplerType[] = + { + // MinMagMipPointUVWClamp + { + D3D12_FILTER_MIN_MAG_MIP_POINT, // Filter mode + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // U address clamping + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // V address clamping + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // W address clamping + 0.0F, // Mip LOD bias + 0, // Max Anisotropy - applies if using ANISOTROPIC filtering only + D3D12_COMPARISON_FUNC_ALWAYS, // Comparison Func - always pass + { 0.0F, 0.0F, 0.0F, 0.0F }, // BorderColor float values - used if TEXTURE_ADDRESS_BORDER is set. + 0.0F, // MinLOD + D3D12_FLOAT32_MAX // MaxLOD + }, + }; + + //-------------------------------------------------------------------------------------- + // Inserts a resource transition operation in the command list + //-------------------------------------------------------------------------------------- + void ResourceBarrier(_In_ ID3D12GraphicsCommandList* pCmdList, _In_ ID3D12Resource* pResource, D3D12_RESOURCE_STATES Before, D3D12_RESOURCE_STATES After, D3D12_RESOURCE_BARRIER_FLAGS Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) + { + D3D12_RESOURCE_BARRIER barrierDesc = {}; + + barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrierDesc.Flags = Flags; + barrierDesc.Transition.pResource = pResource; + barrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrierDesc.Transition.StateBefore = Before; + barrierDesc.Transition.StateAfter = After; + + pCmdList->ResourceBarrier(1, &barrierDesc); + } +} + +Sample::Sample() : + m_frame(0) + , m_showHelp(false) + , m_usingAsyncCompute(false) + , m_renderIndex(0) + , m_terminateThread(false) + , m_fractalMaxIterations(300) +{ + // Renders only 2D, so no need for a depth buffer. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + m_help = std::make_unique(g_SampleTitle, g_SampleDescription, g_HelpButtons, _countof(g_HelpButtons)); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + ResetWindow(); + + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_computeThread = new std::thread(&Sample::AsyncComputeThreadProc, this); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + m_renderFPS.Tick(elapsedTime); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = !m_showHelp; + } + else if (m_showHelp && m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = false; + } + + if (!m_showHelp) + { + if (pad.IsViewPressed()) + { + ExitSample(); + } + + if ((m_gamePadButtons.a == DirectX::GamePad::ButtonStateTracker::PRESSED)) + { + m_usingAsyncCompute = !m_usingAsyncCompute; + } + const float ThumbLeftX = pad.thumbSticks.leftX; + const float ThumbLeftY = pad.thumbSticks.leftY; + const float ThumbRightY = pad.thumbSticks.rightY; + const float RightTrigger = m_gamePadButtons.rightTrigger == DirectX::GamePad::ButtonStateTracker::HELD; + + if (m_gamePadButtons.y == DirectX::GamePad::ButtonStateTracker::PRESSED) + { + ResetWindow(); + } + + if (ThumbLeftX != 0.0f || ThumbLeftY != 0.0f || ThumbRightY != 0.0f) + { + const float ScaleSpeed = 1.0f + RightTrigger * 4.0f; + const float WindowScale = 1.0f + ThumbRightY * -0.25f * ScaleSpeed * elapsedTime; + m_window.x *= WindowScale; + m_window.y *= WindowScale; + m_window.z += m_window.x * ThumbLeftX * elapsedTime * 0.5f; + m_window.w += m_window.y * ThumbLeftY * elapsedTime * 0.5f; + m_windowUpdated = true; + } + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + + // Flip colors for which async compute buffer is being rendered + PIXBeginEvent(commandList, m_renderIndex ? PIX_COLOR(0, 0, 255) : PIX_COLOR(0, 255, 0), L"Render"); + if (m_showHelp) + { + m_help->Render(commandList); + } + else + { + if (!m_usingAsyncCompute) // the user has requested synchronous compute + { // add the compute work to the main command list + if (m_windowUpdated) + { + UpdateFractalData(); + + ID3D12DescriptorHeap* pHeaps[] = { m_SRVDescriptorHeap->Heap(),m_samplerDescriptorHeap->Heap() }; + commandList->SetDescriptorHeaps(_countof(pHeaps), pHeaps); + + EnsureResourceState(ComputeIndex(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + m_resourceState[ComputeIndex()] = ResourceState_Computing; + + commandList->SetComputeRootSignature(m_computeRootSignature.Get()); + + commandList->SetComputeRootConstantBufferView(e_rootParameterCB, m_renderHeap.GpuAddress()); + commandList->SetComputeRootDescriptorTable(e_rootParameterSampler, m_samplerDescriptorHeap->GetGpuHandle(0)); + commandList->SetComputeRootDescriptorTable(e_rootParameterSRV, m_SRVDescriptorHeap->GetGpuHandle(e_iSRV + 2)); // sampler texture, gradient + commandList->SetComputeRootDescriptorTable(e_rootParameterUAV, m_SRVDescriptorHeap->GetGpuHandle(e_iUAV + ComputeIndex())); + + commandList->SetPipelineState(m_computePSO.Get()); + commandList->Dispatch(m_ThreadGroupX, m_ThreadGroupY, 1); + + m_resourceState[ComputeIndex()] = ResourceState_Computed; + SwapRenderComputeIndex(); + } + } + else + { + if (m_resourceState[ComputeIndex()] == ResourceState_Computed) // async has finished with an update, so swap out the buffers + { + m_renderResourceFenceValue++; + EnsureResourceState(RenderIndex(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + m_resourceState[RenderIndex()] = ResourceState_Switching; + SwapRenderComputeIndex(); + } + else if (m_resourceState[ComputeIndex()] == ResourceState_Switching) // the compute buffer has finished being swapped from a pixel shader view to an unordered access view + { // it's now ready for the async compute thread to use + m_resourceState[ComputeIndex()] = ResourceState_ReadyCompute; + } + else if (m_resourceState[ComputeIndex()] == ResourceState_ReadyCompute) // the async compute thread hasn't kicked off and starting using the compute buffer + { + // do nothing, still waiting on async compute to actually do work + } + else if (m_windowUpdated) // need to kick off a new async compute, the user has changed the view area with the controller + { + assert((m_resourceState[RenderIndex()] == ResourceState_ReadyCompute) || (m_resourceState[RenderIndex()] == ResourceState_Rendered)); + m_renderResourceFenceValue++; + EnsureResourceState(RenderIndex(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + m_resourceState[RenderIndex()] = ResourceState_Switching; + SwapRenderComputeIndex(); + } + } + { + assert((m_resourceState[RenderIndex()] == ResourceState_Computed) || (m_resourceState[RenderIndex()] == ResourceState_Rendered)); + RECT outputSize = m_deviceResources->GetOutputSize(); + + m_resourceState[RenderIndex()] = ResourceState_Rendering; + EnsureResourceState(RenderIndex(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + ID3D12DescriptorHeap* pHeaps[] = { m_SRVDescriptorHeap->Heap(), m_samplerDescriptorHeap->Heap() }; + commandList->SetDescriptorHeaps(_countof(pHeaps), pHeaps); + + m_spriteBatch->Begin(commandList); + XMUINT2 texSize(outputSize.right, outputSize.bottom); + XMFLOAT2 texLoc(0, 0); + auto textureSRV = m_SRVDescriptorHeap->GetGpuHandle(e_iSRV + RenderIndex()); + m_spriteBatch->Draw(textureSRV, texSize, texLoc); + m_spriteBatch->End(); + + pHeaps[0] = m_resourceDescriptors->Heap(); + commandList->SetDescriptorHeaps(1, pHeaps); + + m_spriteBatch->Begin(commandList); + + { + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(outputSize.right, outputSize.bottom); + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + wchar_t outputString[256] = {}; + swprintf_s(outputString, 256, L"Simple Compute Context %0.2f fps", m_renderFPS.GetFPS()); + + m_font->DrawString(m_spriteBatch.get(), outputString, pos); + pos.y += m_font->GetLineSpacing(); + if (m_usingAsyncCompute) + { + swprintf_s(outputString, 256, L"Asynchronous compute %0.2f fps", m_computeFPS.GetFPS()); + m_font->DrawString(m_spriteBatch.get(), outputString, pos); + } + else + { + swprintf_s(outputString, 256, L"Synchronous compute %0.2f fps", m_renderFPS.GetFPS()); + m_font->DrawString(m_spriteBatch.get(), outputString, pos); + } + + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), + L"[A] Toggle asynchronous vs. synchronous [View] Exit [Menu] Help", + XMFLOAT2(float(safeRect.left), float(safeRect.bottom) - m_font->GetLineSpacing())); + } + m_spriteBatch->End(); + } + } + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + + // insert a fence for the frame, this allows the compute thread to grab the compute buffer as soon as the view is changed to unordered access + auto commandQueue = m_deviceResources->GetCommandQueue(); + commandQueue->Signal(m_renderResourceFence.Get(), m_renderResourceFenceValue); + + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + m_resourceState[RenderIndex()] = ResourceState_Rendered; + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); + commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto commandList = m_deviceResources->GetCommandList(); + commandList->Reset(m_deviceResources->GetCommandAllocator(), nullptr); + m_graphicsMemory = std::make_unique(device); + + m_resourceState[0] = m_resourceState[1] = ResourceState_ReadyCompute; + + m_resourceDescriptors = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); + + // create compute fence and event + m_computeFenceEvent.Attach(CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS)); + if (!m_computeFenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + DX::ThrowIfFailed( + device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_computeFence.ReleaseAndGetAddressOf()))); + m_computeFence->SetName(L"Compute"); + m_computeFenceValue = 1; + + DX::ThrowIfFailed( + device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_renderResourceFence.ReleaseAndGetAddressOf()))); + m_renderResourceFence->SetName(L"Resource"); + m_renderResourceFenceValue = 1; + + // Initialize resource and descriptor heaps + m_renderHeap = GraphicsMemory::Get().Allocate((size_t)(4 * 1024)); + m_computeHeap = GraphicsMemory::Get().Allocate((size_t)(4 * 1024)); + + // sampler setup + { + m_samplerDescriptorHeap = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + 1); + device->CreateSampler(s_samplerType, m_samplerDescriptorHeap->GetCpuHandle(0)); + } + + m_SRVDescriptorHeap = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + e_iHeapEnd); + + // create fractal texture and views + const D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + const D3D12_RESOURCE_DESC texDesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, 1920, 1080, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); + m_resourceStateFractalTexture[0] = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + DX::ThrowIfFailed( + device->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &texDesc, + m_resourceStateFractalTexture[0], + nullptr, + IID_GRAPHICS_PPV_ARGS(m_fractalTexture[0].ReleaseAndGetAddressOf()))); + m_fractalTexture[0]->SetName(L"Fractal Texture 0"); + + m_resourceStateFractalTexture[1] = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + DX::ThrowIfFailed( + device->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &texDesc, + m_resourceStateFractalTexture[1], + nullptr, + IID_GRAPHICS_PPV_ARGS(m_fractalTexture[1].ReleaseAndGetAddressOf()))); + m_fractalTexture[1]->SetName(L"Fractal Texture 1"); + + m_ThreadGroupX = static_cast(texDesc.Width) / s_numShaderThreads; + m_ThreadGroupY = texDesc.Height / s_numShaderThreads; + + // create gradient textures + const uint32_t GradientTexels[] = { 0xFF000040, 0xFF000080, 0xFF0000C0, 0xFF0000FF, 0xFF0040FF, 0xFF0080FF, 0xFF00C0FF, 0xFF00FFFF }; + const uint32_t RainbowTexels[] = { 0xFF0000FF, 0xFF0080FF, 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000, 0xFF800000, 0xFFFF00FF }; + static_assert(sizeof(RainbowTexels) == sizeof(GradientTexels), "Mismatched size"); + + const D3D12_RESOURCE_DESC gradientTexDesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, 8, 1, 1, 1); + DX::ThrowIfFailed( + device->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &gradientTexDesc, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_fractalColorMap[0].ReleaseAndGetAddressOf()))); + m_fractalColorMap[0]->SetName(L"Fractal Color Map 0"); + + DX::ThrowIfFailed( + device->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &gradientTexDesc, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_fractalColorMap[1].ReleaseAndGetAddressOf()))); + m_fractalColorMap[1]->SetName(L"Fractal Color Map 1"); + + Microsoft::WRL::ComPtr colorMapIntermediate[2]; + { + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD); + + D3D12_RESOURCE_ALLOCATION_INFO info = {}; + info.SizeInBytes = 1024; + info.Alignment = 0; + const D3D12_RESOURCE_DESC tempBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(info); + DX::ThrowIfFailed( + device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &tempBufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(colorMapIntermediate[0].ReleaseAndGetAddressOf()))); + + DX::ThrowIfFailed( + device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &tempBufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(colorMapIntermediate[1].ReleaseAndGetAddressOf()))); + + CD3DX12_SUBRESOURCE_FOOTPRINT descSubresource(gradientTexDesc, D3D12XBOX_TEXTURE_DATA_PITCH_ALIGNMENT); + ResourceBarrier(commandList, m_fractalColorMap[0].Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); + + D3D12_SUBRESOURCE_DATA textureData = {}; + textureData.pData = GradientTexels; + textureData.RowPitch = static_cast(gradientTexDesc.Width * sizeof(uint32_t)); + textureData.SlicePitch = 1; + UpdateSubresources(commandList, m_fractalColorMap[0].Get(), colorMapIntermediate[0].Get(), 0, 0, 1, &textureData); + + ResourceBarrier(commandList, m_fractalColorMap[0].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + textureData.pData = RainbowTexels; + ResourceBarrier(commandList, m_fractalColorMap[1].Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); + UpdateSubresources(commandList, m_fractalColorMap[1].Get(), colorMapIntermediate[1].Get(), 0, 0, 1, &textureData); + ResourceBarrier(commandList, m_fractalColorMap[1].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + + // create uav + device->CreateUnorderedAccessView(m_fractalTexture[0].Get(), nullptr, nullptr, m_SRVDescriptorHeap->GetCpuHandle(e_iUAV)); + device->CreateUnorderedAccessView(m_fractalTexture[1].Get(), nullptr, nullptr, m_SRVDescriptorHeap->GetCpuHandle(e_iUAV + 1)); + + // create srv + device->CreateShaderResourceView(m_fractalTexture[0].Get(), nullptr, m_SRVDescriptorHeap->GetCpuHandle(e_iSRV)); + device->CreateShaderResourceView(m_fractalTexture[1].Get(), nullptr, m_SRVDescriptorHeap->GetCpuHandle(e_iSRV + 1)); + device->CreateShaderResourceView(m_fractalColorMap[0].Get(), nullptr, m_SRVDescriptorHeap->GetCpuHandle(e_iSRV + 2)); + device->CreateShaderResourceView(m_fractalColorMap[1].Get(), nullptr, m_SRVDescriptorHeap->GetCpuHandle(e_iSRV + 3)); + + // load fractal shader + auto computeShaderBlob = DX::ReadData(L"Fractal.cso"); + + // Define root table layout + CD3DX12_DESCRIPTOR_RANGE descRange[e_numRootParameters]; + descRange[e_rootParameterSampler].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); // s0 + descRange[e_rootParameterSRV].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); // t0 + descRange[e_rootParameterUAV].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0); // u0 + + CD3DX12_ROOT_PARAMETER rootParameters[e_numRootParameters]; + rootParameters[e_rootParameterCB].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + rootParameters[e_rootParameterSampler].InitAsDescriptorTable(1, &descRange[e_rootParameterSampler], D3D12_SHADER_VISIBILITY_ALL); + rootParameters[e_rootParameterSRV].InitAsDescriptorTable(1, &descRange[e_rootParameterSRV], D3D12_SHADER_VISIBILITY_ALL); + rootParameters[e_rootParameterUAV].InitAsDescriptorTable(1, &descRange[e_rootParameterUAV], D3D12_SHADER_VISIBILITY_ALL); + + CD3DX12_ROOT_SIGNATURE_DESC rootSignature(_countof(rootParameters), rootParameters); + ID3DBlob *spSerializedSignature; + DX::ThrowIfFailed( + D3D12SerializeRootSignature(&rootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &spSerializedSignature, nullptr)); + + // Create the root signature + DX::ThrowIfFailed( + device->CreateRootSignature( + 0, + spSerializedSignature->GetBufferPointer(), + spSerializedSignature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(m_computeRootSignature.ReleaseAndGetAddressOf()))); + m_computeRootSignature->SetName(L"Compute RS"); + + // Create compute pipeline state + D3D12_COMPUTE_PIPELINE_STATE_DESC descComputePSO = {}; + descComputePSO.pRootSignature = m_computeRootSignature.Get(); + descComputePSO.CS.pShaderBytecode = computeShaderBlob.data(); + descComputePSO.CS.BytecodeLength = computeShaderBlob.size(); + + DX::ThrowIfFailed( + device->CreateComputePipelineState(&descComputePSO, IID_GRAPHICS_PPV_ARGS(m_computePSO.ReleaseAndGetAddressOf()))); + m_computePSO->SetName(L"Compute PSO"); + + // Create compute allocator, command queue and command list + D3D12_COMMAND_QUEUE_DESC descCommandQueue = { D3D12_COMMAND_LIST_TYPE_COMPUTE, 0, D3D12_COMMAND_QUEUE_FLAG_NONE }; + DX::ThrowIfFailed( + device->CreateCommandQueue(&descCommandQueue, IID_GRAPHICS_PPV_ARGS(m_computeCommandQueue.ReleaseAndGetAddressOf()))); + + DX::ThrowIfFailed( + device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, IID_GRAPHICS_PPV_ARGS(m_computeAllocator.ReleaseAndGetAddressOf()))); + + DX::ThrowIfFailed( + device->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_COMPUTE, + m_computeAllocator.Get(), + m_computePSO.Get(), + IID_GRAPHICS_PPV_ARGS(m_computeCommandList.ReleaseAndGetAddressOf()))); + + commandList->Close(); + m_deviceResources->GetCommandQueue()->ExecuteCommandLists(1, CommandListCast(&commandList)); + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); + + ResourceUploadBatch resourceUpload(device); + + resourceUpload.Begin(); + + { + RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + SpriteBatchPipelineStateDescription pd(rtState); + + m_spriteBatch = std::make_unique(device, resourceUpload, pd); + } + + { + m_font = std::make_unique(device, resourceUpload, + L"SegoeUI_18.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::TextFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::TextFont)); + m_ctrlFont = std::make_unique(device, resourceUpload, + L"XboxOneControllerLegendSmall.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::ControllerFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::ControllerFont)); + + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + } + + { + RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + ResourceUploadBatch uploadBatch(device); + uploadBatch.Begin(); + + m_help->RestoreDevice(device, uploadBatch, rtState); + + auto finish = uploadBatch.End(m_deviceResources->GetCommandQueue()); + finish.wait(); + } +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + m_help->SetWindow(size); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_spriteBatch->SetViewport(viewport); +} +#pragma endregion + +void Sample::ResetWindow() +{ + m_window = XMFLOAT4(4.0f, 2.25f, -0.65f, 0.0f); + m_windowUpdated = true; +} + +//-------------------------------------------------------------------------------------- +// Name: UpdateFractalData +// Desc: Updates the dynamic constant buffer with fractal data +//-------------------------------------------------------------------------------------- +void Sample::UpdateFractalData() +{ + const D3D12_RESOURCE_DESC texDesc = m_fractalTexture[0]->GetDesc(); + + SharedGraphicsResource *pUploadHeap = m_usingAsyncCompute ? &m_computeHeap : &m_renderHeap; + + auto pCBFractalData = reinterpret_cast (pUploadHeap->Memory()); + + pCBFractalData->MaxThreadIter = XMFLOAT4(static_cast(texDesc.Width), static_cast(texDesc.Height), static_cast(m_fractalMaxIterations), 0); + pCBFractalData->Window = m_window; +} + +//-------------------------------------------------------------------------------------- +// Name: EnsureResourceState +// Desc: Ensures the fractal texture is in the desired resource state +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +bool Sample::EnsureResourceState(uint32_t index, D3D12_RESOURCE_STATES afterState) +{ + if (m_resourceStateFractalTexture[index] != afterState) + { + auto commandList = m_deviceResources->GetCommandList(); + + ResourceBarrier(commandList, m_fractalTexture[index].Get(), m_resourceStateFractalTexture[index], afterState); + m_resourceStateFractalTexture[index] = afterState; + return true; + } + return false; +} + +void Sample::AsyncComputeThreadProc() +{ + LARGE_INTEGER PerfFreq; + QueryPerformanceFrequency(&PerfFreq); + + LARGE_INTEGER LastFrameTime; + QueryPerformanceCounter(&LastFrameTime); + + while (!m_terminateThread) + { + LARGE_INTEGER CurrentFrameTime; + QueryPerformanceCounter(&CurrentFrameTime); + double DeltaTime = (double)(CurrentFrameTime.QuadPart - LastFrameTime.QuadPart) / (double)PerfFreq.QuadPart; + LastFrameTime = CurrentFrameTime; + + if (m_usingAsyncCompute) + { + if (m_windowUpdated) + { + while (true) + { + if (m_resourceState[ComputeIndex()] == ResourceState_Switching) // render kicked off a resource switch to unordered, + { // check the fence for completed for quickest turn around + if (m_renderResourceFence->GetCompletedValue() >= m_renderResourceFenceValue) // render might also check first and switch the state to ready compute + { + m_resourceState[ComputeIndex()] = ResourceState_ReadyCompute; + break; + } + } + if (m_resourceState[ComputeIndex()] == ResourceState_ReadyCompute) // render detected compute buffer switched to unordered access first + { + break; + } + if (!m_usingAsyncCompute) // user has request synchronous compute + { + break; + } + } + if (!m_usingAsyncCompute) // user has request synchronous compute + { + continue; + } + + m_computeFPS.Tick(static_cast(DeltaTime)); + + UpdateFractalData(); + + // setup the asynchronous compute command list, use a unique command list + PIXBeginEvent(m_computeCommandList.Get(), !m_renderIndex ? PIX_COLOR(0, 0, 255) : PIX_COLOR(0, 255, 0), "Compute"); + + ID3D12DescriptorHeap* pHeaps[] = { m_SRVDescriptorHeap->Heap(), m_samplerDescriptorHeap->Heap() }; + m_computeCommandList->SetDescriptorHeaps(_countof(pHeaps), pHeaps); + + m_computeCommandList->SetComputeRootSignature(m_computeRootSignature.Get()); + + m_computeCommandList->SetComputeRootConstantBufferView(e_rootParameterCB, m_computeHeap.GpuAddress()); + m_computeCommandList->SetComputeRootDescriptorTable(e_rootParameterSampler, m_samplerDescriptorHeap->GetGpuHandle(0)); + m_computeCommandList->SetComputeRootDescriptorTable(e_rootParameterSRV, m_SRVDescriptorHeap->GetGpuHandle(e_iSRV + 3)); // rainbow sampler + m_computeCommandList->SetComputeRootDescriptorTable(e_rootParameterUAV, m_SRVDescriptorHeap->GetGpuHandle(e_iUAV + ComputeIndex())); + + m_computeCommandList->SetPipelineState(m_computePSO.Get()); + m_computeCommandList->Dispatch(m_ThreadGroupX, m_ThreadGroupY, 1); + + PIXEndEvent(m_computeCommandList.Get()); + + // close and execute the command list + m_computeCommandList->Close(); + ID3D12CommandList *tempList = m_computeCommandList.Get(); + m_computeCommandQueue->ExecuteCommandLists(1, &tempList); + + const uint64_t fence = m_computeFenceValue++; + m_computeCommandQueue->Signal(m_computeFence.Get(), fence); + if (m_computeFence->GetCompletedValue() < fence) // block until async compute has completed using a fence + { + m_computeFence->SetEventOnCompletion(fence, m_computeFenceEvent.Get()); + WaitForSingleObject(m_computeFenceEvent.Get(), INFINITE); + } + m_resourceState[ComputeIndex()] = ResourceState_Computed; // signal the buffer is now ready for render thread to use + + m_computeAllocator->Reset(); + m_computeCommandList->Reset(m_computeAllocator.Get(), m_computePSO.Get()); + } + else + { + SwitchToThread(); + } + } + else + { + SwitchToThread(); + } + } +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.h b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.h new file mode 100644 index 0000000000000000000000000000000000000000..e172bca0196f613781124434f2e89ae9e91a674d --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.h @@ -0,0 +1,213 @@ +//-------------------------------------------------------------------------------------- +// SimpleCompute12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "ControllerHelp.h" + +class SmoothedFPS +{ +public: + SmoothedFPS(uint32_t frameInterval = 100) + { + Initialize(frameInterval); + } + + void Initialize(uint32_t frameInterval = 100) + { + m_frameInterval = frameInterval; + m_timeAccumulator = 0.0f; + m_frameAccumulator = 0; + m_smoothedFPS = 0.0f; + } + + void Tick(float DeltaTime) + { + m_timeAccumulator += DeltaTime; + ++m_frameAccumulator; + + if (m_frameAccumulator >= m_frameInterval) + { + m_smoothedFPS = (float)m_frameInterval / m_timeAccumulator; + m_timeAccumulator = 0.0f; + m_frameAccumulator = 0; + } + } + + float GetFPS() const { return m_smoothedFPS; } + +private: + float m_smoothedFPS; + float m_timeAccumulator; + uint32_t m_frameAccumulator; + uint32_t m_frameInterval; +}; + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + + // Properties + bool RequestHDRMode() const { return m_deviceResources ? (m_deviceResources->GetDeviceOptions() & DX::DeviceResources::c_EnableHDR) != 0 : false; } + +private: + struct CB_FractalCS + { + DirectX::XMFLOAT4 MaxThreadIter; + DirectX::XMFLOAT4 Window; + }; + struct Vertex + { + DirectX::XMFLOAT4 position; + DirectX::XMFLOAT2 texcoord; + }; + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void ResetWindow(); + void UpdateFractalData(); + // called by compute side of work, updates the window parameters + + bool EnsureResourceState(_In_range_(0, 1) uint32_t index, D3D12_RESOURCE_STATES afterState); + + void AsyncComputeThreadProc(); + + uint32_t ComputeIndex() const { return 1 - m_renderIndex; } + uint32_t RenderIndex() const { return m_renderIndex; } + void SwapRenderComputeIndex() { m_renderIndex = 1 - m_renderIndex; } + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // on-screen help + std::unique_ptr m_help; + bool m_showHelp; + + // Input devices. + std::unique_ptr m_gamePad; + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // Compute dat + uint32_t m_ThreadGroupX; + uint32_t m_ThreadGroupY; + + SmoothedFPS m_renderFPS; + SmoothedFPS m_computeFPS; + + std::atomic m_terminateThread; + std::thread * m_computeThread; + + std::atomic m_renderIndex; // which bank of fractal data the renderer is using, the value is either 0 or 1, compute is using the inverse + + CB_FractalCS* m_fractalData; // data for compute shader constant buffer on how many iterations on the Mandelbrot set and the bounds + DirectX::XMFLOAT4 m_window; // the bounds for the Mandelbrot set being calculated on the CPU + uint32_t m_fractalMaxIterations; // number of iterations when calculating the Mandelbrot set on the CPU + std::atomic m_windowUpdated; + + // shared data + std::unique_ptr m_SRVDescriptorHeap; // shader resource views for the fractal texture and data + std::unique_ptr m_samplerDescriptorHeap; // shader resource views for the samplers used by the compute shader + DirectX::SharedGraphicsResource m_renderHeap; // renderer version of the fractal constant data + DirectX::SharedGraphicsResource m_computeHeap; // async compute version of the fractal constant data + + // fractal texture data + Microsoft::WRL::ComPtr m_fractalColorMap[2]; // the textures used by the sampler for coloring the computed fractal, one for sync, one for async + Microsoft::WRL::ComPtr m_fractalTexture[2]; // the actual texture generated by the compute shader, double buffered, async and render operating on opposite textures + D3D12_RESOURCE_STATES m_resourceStateFractalTexture[2]; // current state of the fractal texture, unordered or texture view + Microsoft::WRL::ComPtr m_renderResourceFence; // fence used by async compute to start once it's texture has changed to unordered access + uint64_t m_renderResourceFenceValue; + + // compute data + std::atomic m_usingAsyncCompute; + + Microsoft::WRL::ComPtr m_computePSO; + Microsoft::WRL::ComPtr m_computeRootSignature; + Microsoft::WRL::ComPtr m_computeAllocator; + Microsoft::WRL::ComPtr m_computeCommandQueue; + Microsoft::WRL::ComPtr m_computeCommandList; + + Microsoft::WRL::ComPtr m_computeFence; // fence used by the async compute shader to stall waiting for task is complete, so it can signal render when it's done + uint64_t m_computeFenceValue; + Microsoft::WRL::Wrappers::Event m_computeFenceEvent; + + // DirectXTK objects. + std::unique_ptr m_resourceDescriptors; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; + + enum Descriptors + { + TextFont, + ControllerFont, + Count + }; + + enum ResourceBufferState : uint32_t + { + ResourceState_ReadyCompute, + ResourceState_Computing, // async is currently running on this resource buffer + ResourceState_Computed, // async buffer has been updated, no one is using it, moved to this state by async thread, only render will access in this state + ResourceState_Switching, // switching buffer from texture to unordered, from render to compute access + ResourceState_Rendering, // buffer is currently being used by the render system for the frame + ResourceState_Rendered // render frame finished for this resource. possible to switch to computing by render thread if needed + }; + + std::atomic m_resourceState[2]; + + // Indexes for the root parameter table + enum RootParameters : uint32_t + { + e_rootParameterCB = 0, + e_rootParameterSampler, + e_rootParameterSRV, + e_rootParameterUAV, + e_numRootParameters + }; + + // indexes of resources into the descriptor heap + enum DescriptorHeapCount : uint32_t + { + e_cCB = 10, + e_cUAV = 2, + e_cSRV = 4, + }; + enum DescriptorHeapIndex : uint32_t + { + e_iCB = 0, + e_iUAV = e_iCB + e_cCB, + e_iSRV = e_iUAV + e_cUAV, + e_iHeapEnd = e_iSRV + e_cSRV + }; +}; diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.sln b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.sln new file mode 100644 index 0000000000000000000000000000000000000000..f2e59b9370472819358f32f3c5297b859eff36c8 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleCompute12", "SimpleCompute12.vcxproj", "{8E223C2E-4842-414C-BA4D-49963A52C191}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8E223C2E-4842-414C-BA4D-49963A52C191}.Debug|Durango.ActiveCfg = Debug|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Debug|Durango.Build.0 = Debug|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Debug|Durango.Deploy.0 = Debug|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Profile|Durango.ActiveCfg = Profile|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Profile|Durango.Build.0 = Profile|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Profile|Durango.Deploy.0 = Profile|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Release|Durango.ActiveCfg = Release|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Release|Durango.Build.0 = Release|Durango + {8E223C2E-4842-414C-BA4D-49963A52C191}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.vcxproj b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6a41c3339badb11c5470b009a4f0548488721b01 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.vcxproj @@ -0,0 +1,246 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleCompute12 + {8e223c2e-4842-414c-ba4d-49963a52c191} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + + + + + + + + + + Compute + Compute + Compute + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..b2acacd67ea3ef843b87d8525dee0f22313e69d3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/SimpleCompute12.vcxproj.filters @@ -0,0 +1,100 @@ + + + + + 603ab17b-5757-4f4c-a6fd-085c4f8dc83a + + + b1495342-85c3-4494-86de-3249d28c0729 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 66031044-f298-4d16-8045-a09ae20e93f5 + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + + Assets + + + Assets + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleCompute12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleCompute12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/pch.cpp b/XDKSamples/IntroGraphics/SimpleCompute12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleCompute12/pch.h b/XDKSamples/IntroGraphics/SimpleCompute12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..45a8cb6ca3a5100db56b76dc23f250fd5371ec3a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleCompute12/pch.h @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "RenderTargetState.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = {}; + sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast(result)); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Main.cpp b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25d4c7e71017ad0ea40a713a2194f84319910f57 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleDeviceAndSwapChain.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..82e8de6e5bff59cf4967a0d10cd85040f054e5eb --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleDeviceAndSwapChain + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleDeviceAndSwapChain + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..6e88f8100ff4e3900c3f5a8e2f3660fca086158a Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bfc114c07663e9b1b7c4954813f5f48f466dcb1b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.cpp @@ -0,0 +1,344 @@ +//-------------------------------------------------------------------------------------- +// SimpleDeviceAndSwapChain.cpp +// +// Setting up a Direct3D 11 device and swapchain for a Xbox One app +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleDeviceAndSwapChain.h" + +#include "ATGColors.h" + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#define USE_FAST_SEMANTICS + +#define ENABLE_4K + +namespace +{ + const DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; + const UINT c_backBufferCount = 2; +} + +Sample::Sample() : + m_window(nullptr), + m_outputWidth(1920), + m_outputHeight(1080), + m_featureLevel(D3D_FEATURE_LEVEL_11_1), + m_frame(0) +{ +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_window = window; + + CreateDevice(); + + CreateResources(); + + m_gamePad = std::make_unique(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + ExitSample(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + Clear(); + + // Render the frame. + PIXBeginEvent(m_d3dContext.Get(), PIX_COLOR_DEFAULT, L"Render"); + + m_batch->Begin(); + + RECT fullscreen = { 0, 0, m_outputWidth, m_outputHeight }; + m_batch->Draw(m_background.Get(), fullscreen); + + m_batch->End(); + + PIXEndEvent(m_d3dContext.Get()); + + // Show the new frame. + PIXBeginEvent(m_d3dContext.Get(), PIX_COLOR_DEFAULT, L"Present"); + Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(m_d3dContext.Get()); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ +#ifdef USE_FAST_SEMANTICS + // When using 11.X Fast Semantics, you need to do the swapchain rotation explicitly + DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_renderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); +#endif + + PIXBeginEvent(m_d3dContext.Get(), PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + m_d3dContext->ClearRenderTargetView(m_renderTargetView.Get(), ATG::Colors::Background); + m_d3dContext->ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + m_d3dContext->OMSetRenderTargets(1, m_renderTargetView.GetAddressOf(), m_depthStencilView.Get()); + + // Set the viewport. + CD3D11_VIEWPORT viewport(0.0f, 0.0f, static_cast(m_outputWidth), static_cast(m_outputHeight)); + m_d3dContext->RSSetViewports(1, &viewport); + + m_batch->SetViewport(viewport); + + PIXEndEvent(m_d3dContext.Get()); +} + +// Presents the back buffer contents to the screen. +void Sample::Present() +{ + PIXBeginEvent(m_d3dContext.Get(), PIX_COLOR_DEFAULT, L"Present"); + +#ifdef USE_FAST_SEMANTICS + // When using 11.X Fast Semantics, you need to decompress the render target before presenting + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + c_backBufferFormat, D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); +#endif + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + DX::ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + PIXEndEvent(m_d3dContext.Get()); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + // + // Xbox One apps need to explictly suspend the GPU. + // + // Ensure that no other threads are rendering when this call is made. + // + + m_d3dContext->Suspend(0); +} + +void Sample::OnResuming() +{ + m_d3dContext->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDevice() +{ + // + // Classic Win32 and UWP apps use D3D11CreateDevice which is supported on Xbox One, but + // use of D3D11XCreateDeviceX is recommended. + // + // Note that D3D11CreateDeviceAndSwapChain is not supported for Xbox One and is not recommended generally + // + + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + +#ifdef USE_FAST_SEMANTICS + // Opt-in to 11.X Fast Semantics + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; +#endif + + // Create the Direct3D 11 API device object and a corresponding context. + DX::ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + + // Recommended debug layer settings +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + +#if defined(ENABLE_4K) && (_XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */) + // Opt-in to 4K swapchains on Xbox One X + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputWidth = 3840; + m_outputHeight = 2160; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else +#endif +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); +#endif + + // Initialize device dependent objects here (independent of window size). + m_graphicsMemory = std::make_unique(m_d3dDevice.Get(), c_backBufferCount); + + m_batch = std::make_unique(m_d3dContext.Get()); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateResources() +{ + // Determine the render target size in pixels. + UINT backBufferWidth = static_cast(m_outputWidth); + UINT backBufferHeight = static_cast(m_outputHeight); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + DX::ThrowIfFailed(m_swapChain->ResizeBuffers(c_backBufferCount, backBufferWidth, backBufferHeight, c_backBufferFormat, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI Device from the D3D Device. + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + DX::ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = c_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = c_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Obtain the backbuffer for this window which will be the final 3D rendertarget. + DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + // Create a view interface on the rendertarget to use on bind. + DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView(m_renderTarget.Get(), nullptr, m_renderTargetView.ReleaseAndGetAddressOf())); + + // Allocate a 2-D surface as the depth/stencil buffer and + // create a DepthStencil view on this surface to use on bind. + CD3D11_TEXTURE2D_DESC depthStencilDesc(c_depthBufferFormat, backBufferWidth, backBufferHeight, 1, 1, D3D11_BIND_DEPTH_STENCIL); + + DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&depthStencilDesc, nullptr, m_depthStencil.ReleaseAndGetAddressOf())); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &depthStencilViewDesc, m_depthStencilView.ReleaseAndGetAddressOf())); + + // Initialize windows-size dependent objects here. + DX::ThrowIfFailed(CreateDDSTextureFromFileEx(m_d3dDevice.Get(), + m_outputHeight > 1080 ? L"3840x2160.dds" : L"1920x1080.dds", 0, + D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, true, + nullptr, m_background.ReleaseAndGetAddressOf())); +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h new file mode 100644 index 0000000000000000000000000000000000000000..ea70e5fe9c4f213dd1126d6bb148c5b77d1b7ceb --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.h @@ -0,0 +1,73 @@ +//-------------------------------------------------------------------------------------- +// SimpleDeviceAndSwapChain.h +// +// Setting up a Direct3D 11 device and swapchain for a Xbox One app +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + void Present(); + + void CreateDevice(); + void CreateResources(); + + // Application state + IUnknown* m_window; + int m_outputWidth; + int m_outputHeight; + + // Direct3D Objects + D3D_FEATURE_LEVEL m_featureLevel; + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + + // Rendering resources + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_renderTargetView; + Microsoft::WRL::ComPtr m_depthStencilView; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_batch; + + Microsoft::WRL::ComPtr m_background; +}; diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.sln b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.sln new file mode 100644 index 0000000000000000000000000000000000000000..4aea1fa1200b8f6020e1b611c06899b7204a9236 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleDeviceAndSwapChain", "SimpleDeviceAndSwapChain.vcxproj", "{9C58EF8D-D3DD-4519-8032-E7CF48A4224F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Debug|Durango.ActiveCfg = Debug|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Debug|Durango.Build.0 = Debug|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Debug|Durango.Deploy.0 = Debug|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Profile|Durango.ActiveCfg = Profile|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Profile|Durango.Build.0 = Profile|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Profile|Durango.Deploy.0 = Profile|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Release|Durango.ActiveCfg = Release|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Release|Durango.Build.0 = Release|Durango + {9C58EF8D-D3DD-4519-8032-E7CF48A4224F}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.vcxproj b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..a282bae109a8924b51460746f9f96cc1f013ec00 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.vcxproj @@ -0,0 +1,208 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleDeviceAndSwapChain + {9c58ef8d-d3dd-4519-8032-e7cf48a4224f} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..ae6785aa398dd78e74dc33dc7158db66ae48d346 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/SimpleDeviceAndSwapChain.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + 48f08fdf-4efe-491b-8044-3307d561094e + + + fe05c5ff-d8a5-4f3b-9aae-7acc46a71501 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + e05a5105-2622-468f-9b76-94ae0c7a2f86 + + + + + + + Common + + + Common + + + ATG Tool Kit + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/StepTimer.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Telemetry.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/pch.cpp b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..df90bdac9c907b9ba2a998c9e066f493d65856d4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390868 /* XDK Edition 161000 */ +#error This sample requires the October 2016 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "DDSTextureLoader.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SpriteBatch.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Main.cpp b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25d4c7e71017ad0ea40a713a2194f84319910f57 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleDeviceAndSwapChain.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..346f8d0ebc2e349ab7d6ff57f80ddc9023a8f28b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleDeviceAndSwapChain + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleDeviceAndSwapChain + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Readme.docx b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..10ad2b75ab557ed06391a5047f589d98aed66a5a Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.cpp b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a56178feeab82f53f49be89690663e268d43b0f7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.cpp @@ -0,0 +1,467 @@ +//-------------------------------------------------------------------------------------- +// SimpleDeviceAndSwapChain.cpp +// +// Setting up a Direct3D 12 device and swapchain for a Xbox One app +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleDeviceAndSwapChain.h" + +#include "ATGColors.h" + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#define ENABLE_4K + +namespace +{ + const DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; +} + +Sample::Sample() : + m_window(nullptr), + m_outputWidth(1920), + m_outputHeight(1080), + m_featureLevel(D3D_FEATURE_LEVEL_12_0), + m_backBufferIndex(0), + m_frame(0), + m_fenceValues{} +{ +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_window = window; + + CreateDevice(); + CreateResources(); + + m_gamePad = std::make_unique(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + ExitSample(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + Clear(); + + // Render the frame. + PIXBeginEvent(m_commandList.Get(), PIX_COLOR_DEFAULT, L"Render"); + + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; + m_commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + m_batch->Begin(m_commandList.Get()); + + RECT fullscreen = { 0, 0, m_outputWidth, m_outputHeight }; + + m_batch->Draw(m_resourceDescriptors->GetGpuHandle(Descriptors::Background), + GetTextureSize(m_background.Get()), fullscreen); + + m_batch->End(); + + PIXEndEvent(m_commandList.Get()); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + Present(); + m_graphicsMemory->Commit(m_commandQueue.Get()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + // Reset command list and allocator. + DX::ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + DX::ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + + // Clear the views. + PIXBeginEvent(m_commandList.Get(), PIX_COLOR_DEFAULT, L"Clear"); + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + CD3DX12_CPU_DESCRIPTOR_HANDLE dsvDescriptor(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + m_commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + m_commandList->ClearRenderTargetView(rtvDescriptor, ATG::Colors::Background, 0, nullptr); + m_commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + D3D12_VIEWPORT viewport = { 0.0f, 0.0f, static_cast(m_outputWidth), static_cast(m_outputHeight), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH }; + D3D12_RECT scissorRect = { 0, 0, m_outputWidth, m_outputHeight }; + m_commandList->RSSetViewports(1, &viewport); + m_commandList->RSSetScissorRects(1, &scissorRect); + + m_batch->SetViewport(viewport); + + PIXEndEvent(m_commandList.Get()); +} + +// Submits the command list to the GPU and presents the back buffer contents to the screen. +void Sample::Present() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + + // Send the command list off to the GPU for processing. + DX::ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + DX::ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + // + // Xbox One apps need to explictly suspend the GPU. + // + // Ensure that no other threads are rendering when this call is made. + // + + m_commandQueue->SuspendX(0); +} + +void Sample::OnResuming() +{ + m_commandQueue->ResumeX(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDevice() +{ + // + // Classic Win32 and UWP apps use D3D12CreateDevice which is supported on Xbox One, but + // use of D3D12XboxCreateDevice is recommended. + // + + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + DX::ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = c_swapBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + m_dsvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < c_swapBufferCount; n++) + { + DX::ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + DX::ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + DX::ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw Platform::Exception::CreateException(HRESULT_FROM_WIN32(GetLastError())); + } + +#if defined(ENABLE_4K) && (_XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */) + // Opt-in to 4K swapchains on Xbox One X + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputWidth = 3840; + m_outputHeight = 2160; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else +#endif +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080)\n"); +#endif + + // Initialize device dependent objects here (independent of window size). + m_graphicsMemory = std::make_unique(m_d3dDevice.Get()); + + m_resourceDescriptors = std::make_unique(m_d3dDevice.Get(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateResources() +{ + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < c_swapBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + UINT backBufferWidth = static_cast(m_outputWidth); + UINT backBufferHeight = static_cast(m_outputHeight); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + DX::ThrowIfFailed(m_swapChain->ResizeBuffers(c_swapBufferCount, backBufferWidth, backBufferHeight, c_backBufferFormat, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + DX::ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = c_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = c_swapBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_MATCH_XBOX360_AND_PC; + + // Create a swap chain for the window. + DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < c_swapBufferCount; n++) + { + DX::ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + if (swprintf_s(name, L"Render target %u", n) > 0) + { + m_renderTargets[n]->SetName(name); + } + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + c_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + CD3DX12_CLEAR_VALUE depthOptimizedClearValue(c_depthBufferFormat, 1.0f, 0); + + DX::ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = c_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + + // Initialize windows-size dependent objects here. + ResourceUploadBatch resourceUpload(m_d3dDevice.Get()); + + resourceUpload.Begin(); + + DX::ThrowIfFailed( + CreateDDSTextureFromFileEx(m_d3dDevice.Get(), resourceUpload, + m_outputHeight > 1080 ? L"3840x2160.dds" : L"1920x1080.dds", + 0, D3D12_RESOURCE_FLAG_NONE, DDS_LOADER_FORCE_SRGB, + m_background.ReleaseAndGetAddressOf())); + + CreateShaderResourceView(m_d3dDevice.Get(), m_background.Get(), + m_resourceDescriptors->GetCpuHandle(Descriptors::Background)); + + RenderTargetState rtState(c_backBufferFormat, c_depthBufferFormat); + + SpriteBatchPipelineStateDescription pd(rtState); + m_batch = std::make_unique(m_d3dDevice.Get(), resourceUpload, pd); + + auto uploadResourcesFinished = resourceUpload.End(m_commandQueue.Get()); + + uploadResourcesFinished.wait(); +} + +void Sample::WaitForGpu() +{ + // Schedule a Signal command in the GPU queue. + DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), m_fenceValues[m_backBufferIndex])); + + // Wait until the Signal has been processed. + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; +} + +void Sample::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % c_swapBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.h new file mode 100644 index 0000000000000000000000000000000000000000..8066feead9f1372edd86e140ab19eb1d3a4ad6fc --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.h @@ -0,0 +1,93 @@ +//-------------------------------------------------------------------------------------- +// SimpleDeviceAndSwapChain.h +// +// Setting up a Direct3D 12 device and swapchain for a Xbox One app +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + void Present(); + + void CreateDevice(); + void CreateResources(); + + void WaitForGpu(); + void MoveToNextFrame(); + + // Application state + IUnknown* m_window; + int m_outputWidth; + int m_outputHeight; + + // Direct3D Objects + D3D_FEATURE_LEVEL m_featureLevel; + static const UINT c_swapBufferCount = 2; + UINT m_backBufferIndex; + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + UINT m_rtvDescriptorSize; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_dsvDescriptorSize; + Microsoft::WRL::ComPtr m_commandAllocators[c_swapBufferCount]; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[c_swapBufferCount]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Rendering resources + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[c_swapBufferCount]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + std::unique_ptr m_resourceDescriptors; + Microsoft::WRL::ComPtr m_background; + + enum Descriptors + { + Background, + Count + }; + + std::unique_ptr m_batch; +}; diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.sln b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.sln new file mode 100644 index 0000000000000000000000000000000000000000..29caf8a5578062e0ab67f657a61325fae8671ce7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleDeviceAndSwapChain", "SimpleDeviceAndSwapChain.vcxproj", "{4A74D2FB-B812-4B73-ABF9-9D3A0844A896}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Debug|Durango.ActiveCfg = Debug|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Debug|Durango.Build.0 = Debug|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Debug|Durango.Deploy.0 = Debug|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Profile|Durango.ActiveCfg = Profile|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Profile|Durango.Build.0 = Profile|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Profile|Durango.Deploy.0 = Profile|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Release|Durango.ActiveCfg = Release|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Release|Durango.Build.0 = Release|Durango + {4A74D2FB-B812-4B73-ABF9-9D3A0844A896}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.vcxproj b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..c8914ea21b14e2f59bfe963930921244928e1553 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.vcxproj @@ -0,0 +1,208 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleDeviceAndSwapChain + {4a74d2fb-b812-4b73-abf9-9d3a0844a896} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..7e41e1e7ac4363dce5312c288605b0d3dc3e861f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/SimpleDeviceAndSwapChain.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + 92d62a03-a3cf-474e-ac8e-90d2b97d52fc + + + 8eb06270-1060-41bf-b4e2-4a5beaf101ca + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 1321b9a2-4594-47a3-97d5-6f90ad93086e + + + + + + + Common + + + Common + + + ATG Tool Kit + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/pch.cpp b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/pch.h b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..e9d3b146b03d054557385396888b44cfe7c271e6 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleDeviceAndSwapChain12/pch.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390868 /* XDK Edition 161000 */ +#error This sample requires the October 2016 XDK or later +#endif + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "DDSTextureLoader.h" +#include "DescriptorHeap.h" +#include "DirectXHelpers.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "RenderTargetState.h" +#include "ResourceUploadBatch.h" +#include "SpriteBatch.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleInstancing/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleInstancing/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Main.cpp b/XDKSamples/IntroGraphics/SimpleInstancing/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33cc42434a44c7c24f8d13f4a71bc630a1abd836 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleInstancing.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleInstancing/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..68578d27a20025a03b00062e85b6521a94f2dc23 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleInstancing + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleInstancing + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/PixelShader.hlsl b/XDKSamples/IntroGraphics/SimpleInstancing/PixelShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..0cf6f23e525ebc82ff981e5a12cd1b52bfa90896 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/PixelShader.hlsl @@ -0,0 +1,2 @@ +// PixelShader.hlsl file to provide an MSBuild target for the SimpleInstancing pixel-shader entry point +#include "SimpleInstancing.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Readme.docx b/XDKSamples/IntroGraphics/SimpleInstancing/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..6e72446c04fb0af32cec919c32763a510bdf1578 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Shared.h b/XDKSamples/IntroGraphics/SimpleInstancing/Shared.h new file mode 100644 index 0000000000000000000000000000000000000000..2cd0992a0caa3edd1ed5fcee4f6eb5a4737fd433 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/Shared.h @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// Shared.h +// +// Shared declarations between shaders (HLSL) and C++ source. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +static const unsigned int c_pointLightCount = 25; diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3dab54074ca013ded8cfb28e9ed0afbb3fb3d64 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.cpp @@ -0,0 +1,587 @@ +//-------------------------------------------------------------------------------------- +// SimpleInstancing.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleInstancing.h" + +#include "ATGColors.h" +#include "ControllerFont.h" +#include "ReadData.h" + +using namespace DirectX; +using namespace DirectX::PackedVector; + +using Microsoft::WRL::ComPtr; + +namespace +{ + //-------------------------------------------------------------------------------------- + // Constants + //-------------------------------------------------------------------------------------- + const uint32_t c_maxInstances = 20000; + const uint32_t c_startInstanceCount = 5000; + const uint32_t c_minInstanceCount = 1000; + const float c_boxBounds = 60.0f; + const size_t c_cubeIndexCount = 36; + const float c_velocityMultiplier = 500.0f; + + //-------------------------------------------------------------------------------------- + // Cube vertex definition + //-------------------------------------------------------------------------------------- + struct Vertex + { + XMFLOAT3 pos; + XMFLOAT3 norm; + }; +} + +Sample::Sample() : + m_frame(0), + m_usedInstanceCount(c_startInstanceCount), + m_lights{}, + m_pitch(0.0f), + m_yaw(0.0f) +{ + XMStoreFloat4x4(&m_proj, XMMatrixIdentity()); + + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::ButtonState::PRESSED) + { + ResetSimulation(); + } + + if (m_gamePadButtons.rightShoulder == GamePad::ButtonStateTracker::ButtonState::PRESSED) + { + m_usedInstanceCount = std::min(c_maxInstances, m_usedInstanceCount + 1000); + } + else if (m_gamePadButtons.leftShoulder == GamePad::ButtonStateTracker::ButtonState::PRESSED) + { + m_usedInstanceCount = std::max(c_minInstanceCount, m_usedInstanceCount - 1000); + } + + if (pad.IsLeftStickPressed()) + { + m_yaw = m_pitch = 0.f; + } + else + { + m_yaw += pad.thumbSticks.leftX * 0.1f; + m_pitch += pad.thumbSticks.leftY * 0.1f; + } + } + else + { + m_gamePadButtons.Reset(); + } + + // Limit to avoid looking directly up or down + float limit = XM_PI / 2.0f - 0.01f; + m_pitch = std::max(-limit, m_pitch); + m_pitch = std::min(+limit, m_pitch); + + if (m_yaw > XM_PI) + { + m_yaw -= XM_PI * 2.f; + } + else if (m_yaw < -XM_PI) + { + m_yaw += XM_PI * 2.f; + } + + XMVECTOR lookAt = XMVectorSet( + sinf(m_yaw), + m_pitch, + cosf(m_yaw), + 0); + + // Update transforms and constant buffer. + XMMATRIX camera = XMMatrixLookAtLH(g_XMZero, lookAt, g_XMIdentityR1); + XMMATRIX proj = XMLoadFloat4x4(&m_proj); + XMMATRIX clip = XMMatrixTranspose(XMMatrixMultiply(camera, proj)); + ReplaceBufferContents(m_vertexConstants.Get(), sizeof(XMMATRIX), &clip); + + // Overwrite our current instance vertex buffer with new data. + ReplaceBufferContents(m_instanceData.Get(), sizeof(Instance) * m_usedInstanceCount, m_CPUInstanceData.get()); + + // Update instance data for the next frame. + for (size_t i = 1; i < m_usedInstanceCount; ++i) + { + // Update positions... + float velocityMultiplier = i <= c_pointLightCount ? 5.0f * c_velocityMultiplier : c_velocityMultiplier; + XMVECTOR position = XMLoadFloat4(&m_CPUInstanceData[i].positionAndScale); + position += m_velocities[i] * elapsedTime * velocityMultiplier; + XMStoreFloat4(&m_CPUInstanceData[i].positionAndScale, position); + + float X = m_CPUInstanceData[i].positionAndScale.x; + float Y = m_CPUInstanceData[i].positionAndScale.y; + float Z = m_CPUInstanceData[i].positionAndScale.z; + + bool bounce = false; + + // If an instance pops out of bounds in any dimension, reverse velocity in that dimension... + if (X < -c_boxBounds || X > c_boxBounds) + { + m_velocities[i] *= XMVectorSet(-1.0f, 1.0f, 1.0f, 1.0f); + bounce = true; + } + if (Y < -c_boxBounds || Y > c_boxBounds) + { + m_velocities[i] *= XMVectorSet(1.0f, -1.0f, 1.0f, 1.0f); + bounce = true; + } + if (Z < -c_boxBounds || Z > c_boxBounds) + { + m_velocities[i] *= XMVectorSet(1.0f, 1.0f, -1.0f, 1.0f); + bounce = true; + } + + // Apply bounce here. + if (bounce) + { + position = XMLoadFloat4(&m_CPUInstanceData[i].positionAndScale); + position += m_velocities[i] * elapsedTime * c_velocityMultiplier; + XMStoreFloat4(&m_CPUInstanceData[i].positionAndScale, position); + } + + // Set up constant buffer with point light info. + if (i <= c_pointLightCount) + { + m_lights.pointPositions[i - 1] = m_CPUInstanceData[i].positionAndScale; + } + + XMVECTOR q = XMLoadFloat4(&m_CPUInstanceData[i].quaternion); + q = XMQuaternionNormalizeEst(XMQuaternionMultiply(m_rotationQuaternions[i], q)); + XMStoreFloat4(&m_CPUInstanceData[i].quaternion, q); + } + + // Update the D3D11 constant buffer with the new lighting constant data. + ReplaceBufferContents(m_pixelConstants.Get(), sizeof(Lights), &m_lights); + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Use the default blend + context->OMSetBlendState(nullptr, nullptr, D3D11_DEFAULT_SAMPLE_MASK); + + // Set input assembler state. + context->IASetInputLayout(m_inputLayout.Get()); + + // We're rendering a triangle list. + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // Set up the vertex buffers. We have 3 streams: + // Stream 1 contains per-primitive vertices defining the cubes. + // Stream 2 contains the per-instance data for scale, position and orientation + // Stream 3 contains the per-instance data for color. + UINT Strides[] = { sizeof(Vertex), sizeof(Instance), sizeof(uint32_t) }; + UINT Offsets[] = { 0, 0, 0 }; + ID3D11Buffer* Buffers[] = { m_vertexBuffer.Get(), m_instanceData.Get(), m_boxColors.Get() }; + context->IASetVertexBuffers(0, _countof(Strides), Buffers, Strides, Offsets); + + // The per-instance data is referenced by index... + context->IASetIndexBuffer(m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0); + + // Apply the constants for the vertex and pixel shaders. + context->VSSetConstantBuffers(0, 1, m_vertexConstants.GetAddressOf()); + context->PSSetConstantBuffers(0, 1, m_pixelConstants.GetAddressOf()); + + // Set shaders. + context->VSSetShader(m_vertexShader.Get(), nullptr, 0); + context->PSSetShader(m_pixelShader.Get(), nullptr, 0); + + // Draw the entire scene... + context->DrawIndexedInstanced(c_cubeIndexCount, m_usedInstanceCount, 0, 0, 0); + + // Draw UI + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + m_batch->Begin(); + + wchar_t str[32] = {}; + swprintf_s(str, L"Instancing count: %u", m_usedInstanceCount); + m_smallFont->DrawString(m_batch.get(), str, XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::White); + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + L"[LThumb] Rotate [A] Reset [LB]/[RB] Change instance count [View] Exit", + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + // Use linear clear color for gamma-correct rendering + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers. +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + m_batch = std::make_unique(context); + + // Create input layout (must match declaration of Vertex). + static const D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = + { + // SemanticName SemanticIndex Format InputSlot AlignedByteOffset InputSlotClass InstancedDataStepRate + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // Vertex local position + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // Vertex normal + { "I_ROTATION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, // Instance rotation quaternion + { "I_POSSCALE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, // Instance position and scale (scale in "w") + { "I_COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 2, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, // Instance color + }; + + // Load and create shaders. + { + auto shaderBytecode = DX::ReadData(L"VertexShader.cso"); + + DX::ThrowIfFailed( + device->CreateVertexShader(shaderBytecode.data(), shaderBytecode.size(), nullptr, m_vertexShader.ReleaseAndGetAddressOf()) + ); + + DX::ThrowIfFailed( + device->CreateInputLayout(inputElementDesc, _countof(inputElementDesc), shaderBytecode.data(), shaderBytecode.size(), m_inputLayout.ReleaseAndGetAddressOf()) + ); + } + + { + auto shaderBytecode = DX::ReadData(L"PixelShader.cso"); + + DX::ThrowIfFailed( + device->CreatePixelShader(shaderBytecode.data(), shaderBytecode.size(), nullptr, m_pixelShader.ReleaseAndGetAddressOf()) + ); + } + + // Create and initialize the vertex buffer defining a cube. + { + static const Vertex vertices[] = + { + { XMFLOAT3(-1, -1, -1), XMFLOAT3(0, 0, -1) }, + { XMFLOAT3( 1, -1, -1), XMFLOAT3(0, 0, -1) }, + { XMFLOAT3( 1, 1, -1), XMFLOAT3(0, 0, -1) }, + { XMFLOAT3(-1, 1, -1), XMFLOAT3(0, 0, -1) }, // Z negative face + + { XMFLOAT3( 1, -1, 1), XMFLOAT3(0, 0, 1) }, + { XMFLOAT3(-1, -1, 1), XMFLOAT3(0, 0, 1) }, + { XMFLOAT3(-1, 1, 1), XMFLOAT3(0, 0, 1) }, + { XMFLOAT3( 1, 1, 1), XMFLOAT3(0, 0, 1) }, // Z Positive face + + { XMFLOAT3(-1, -1, -1), XMFLOAT3(-1, 0, 0) }, + { XMFLOAT3(-1, 1, -1), XMFLOAT3(-1, 0, 0) }, + { XMFLOAT3(-1, 1, 1), XMFLOAT3(-1, 0, 0) }, + { XMFLOAT3(-1, -1, 1), XMFLOAT3(-1, 0, 0) }, // X negative face + + { XMFLOAT3( 1, 1, -1), XMFLOAT3( 1, 0, 0) }, + { XMFLOAT3( 1, -1, -1), XMFLOAT3( 1, 0, 0) }, + { XMFLOAT3( 1, -1, 1), XMFLOAT3( 1, 0, 0) }, + { XMFLOAT3( 1, 1, 1), XMFLOAT3( 1, 0, 0) }, // X Positive face + + { XMFLOAT3(-1, -1, 1), XMFLOAT3(0, -1, 0) }, + { XMFLOAT3( 1, -1, 1), XMFLOAT3(0, -1, 0) }, + { XMFLOAT3( 1, -1, -1), XMFLOAT3(0, -1, 0) }, + { XMFLOAT3(-1, -1, -1), XMFLOAT3(0, -1, 0) }, // Y negative face + + { XMFLOAT3( 1, 1, 1), XMFLOAT3(0, 1, 0) }, + { XMFLOAT3(-1, 1, 1), XMFLOAT3(0, 1, 0) }, + { XMFLOAT3(-1, 1, -1), XMFLOAT3(0, 1, 0) }, + { XMFLOAT3( 1, 1, -1), XMFLOAT3(0, 1, 0) }, // Y Positive face + }; + + D3D11_SUBRESOURCE_DATA initialData = { vertices, 0, 0 }; + + CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE); + bufferDesc.StructureByteStride = sizeof(Vertex); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, &initialData, m_vertexBuffer.ReleaseAndGetAddressOf()) + ); + } + + // Create vertex buffers with per-instance data. + { + CD3D11_BUFFER_DESC bufferDesc(sizeof(Instance) * c_maxInstances, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + bufferDesc.StructureByteStride = sizeof(Instance); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, nullptr, m_instanceData.ReleaseAndGetAddressOf()) + ); + } + + // Create a static vertex buffer with color data. + { + static const XMVECTORF32 c_bigColor = { 1.f, 1.f, 1.f, 0.f }; + uint32_t colors[c_maxInstances]; + colors[0] = XMCOLOR(c_bigColor); + for (uint32_t i = 1; i < c_maxInstances; ++i) + { + if (i <= c_pointLightCount) + { + m_lights.pointColors[i - 1] = XMFLOAT4(FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), 1.0f); + colors[i] = XMCOLOR(m_lights.pointColors[i - 1].x, m_lights.pointColors[i - 1].y, m_lights.pointColors[i - 1].z, 1.f); + } + else + { + colors[i] = XMCOLOR(FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), 0.f); + } + } + + D3D11_SUBRESOURCE_DATA initialData = { colors, 0, 0 }; + + CD3D11_BUFFER_DESC bufferDesc(sizeof(uint32_t) * c_maxInstances, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE); + bufferDesc.StructureByteStride = sizeof(uint32_t); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, &initialData, m_boxColors.ReleaseAndGetAddressOf()) + ); + } + + // Create and initialize the index buffer for the cube geometry. + { + static const uint16_t indices[] = + { + 0, 2, 1, + 0, 3, 2, + 4, 6, 5, + 4, 7, 6, + 8, 10, 9, + 8, 11, 10, + 12, 14, 13, + 12, 15, 14, + 16, 18, 17, + 16, 19, 18, + 20, 22, 21, + 20, 23, 22, + }; + + D3D11_SUBRESOURCE_DATA initialData = { indices, 0, 0 }; + + CD3D11_BUFFER_DESC bufferDesc(sizeof(indices), D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_IMMUTABLE); + bufferDesc.StructureByteStride = sizeof(uint16_t); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, &initialData, m_indexBuffer.ReleaseAndGetAddressOf()) + ); + } + + // Create the vertex shader constant buffer. + { + CD3D11_BUFFER_DESC bufferDesc(sizeof(XMMATRIX), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, nullptr, m_vertexConstants.ReleaseAndGetAddressOf()) + ); + } + + // Create the pixel shader (lighting) constant buffer. + { + static_assert((sizeof(Lights) % 16) == 0, "Constant buffer must always be 16-byte aligned"); + + CD3D11_BUFFER_DESC bufferDesc(sizeof(Lights), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, nullptr, m_pixelConstants.ReleaseAndGetAddressOf()) + ); + } + + m_CPUInstanceData.reset(new Instance[c_maxInstances]); + m_rotationQuaternions.reset(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * c_maxInstances, 16))); + m_velocities.reset(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * c_maxInstances, 16))); + + // Set up the position and scale for the container box. Scale is negative to turn the box inside-out + // (this effectively reverses the normals and backface culling). + // Scale the outside box to slightly larger than our scene boundary, so bouncing boxes never actually clip it. + m_CPUInstanceData[0].positionAndScale = XMFLOAT4(0.0f, 0.0f, 0.0f, -(c_boxBounds + 5)); + m_CPUInstanceData[0].quaternion = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); + + // Initialize the directional light. + XMStoreFloat4(&m_lights.directional, XMVector3Normalize(XMVectorSet(1.0f, 4.0f, -2.0f, 0))); + + // Initialize the positions/state of all the cubes in the scene. + ResetSimulation(); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + // Initialize the projection matrix. + auto size = m_deviceResources->GetOutputSize(); + + auto device = m_deviceResources->GetD3DDevice(); + m_smallFont = std::make_unique(device, (size.bottom > 1080) ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, (size.bottom > 1080) ? L"XboxOneControllerLegend.spritefont" : L"XboxOneControllerLegendSmall.spritefont"); + + XMMATRIX proj = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.1f, 500.0f); + XMStoreFloat4x4(&m_proj, proj); +} +#pragma endregion + +void Sample::ReplaceBufferContents(ID3D11Buffer* buffer, size_t bufferSize, const void* data) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + D3D11_MAPPED_SUBRESOURCE mapped; + + DX::ThrowIfFailed( + context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped) + ); + + memcpy(mapped.pData, data, bufferSize); + context->Unmap(buffer, 0); +} + +void Sample::ResetSimulation() +{ + // Reset positions to starting point, and orientations to identity. + // Note that instance 0 is the scene bounding box, and the position, orientation and scale are static (i.e. never update). + for (size_t i = 1; i < c_maxInstances; ++i) + { + m_CPUInstanceData[i].positionAndScale = XMFLOAT4(0.0f, 0.0f, c_boxBounds / 2.0f, FloatRand(0.1f, 0.4f)); + m_CPUInstanceData[i].quaternion = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); + + // For the first c_pointLightCount in the updated array, we scale up by a small factor so they stand out, and + // update the light constant data with their positions. + if (i <= c_pointLightCount) + { + m_CPUInstanceData[i].positionAndScale.w = 1.53f; + m_lights.pointPositions[i - 1] = m_CPUInstanceData[i].positionAndScale; + } + + // Apply a random spin to each instance. + m_rotationQuaternions[i] = XMQuaternionRotationAxis(XMVector3Normalize(XMVectorSet(FloatRand(), FloatRand(), FloatRand(), 0)), FloatRand(0.001f, 0.1f)); + + // ...and a random velocity. + m_velocities[i] = XMVectorSet(FloatRand(-0.01f, 0.01f), FloatRand(-0.01f, 0.01f), FloatRand(-0.01f, 0.01f), 0); + } +} + +inline float Sample::FloatRand(float lowerBound, float upperBound) +{ + if (lowerBound == upperBound) + return lowerBound; + + std::uniform_real_distribution dist(lowerBound, upperBound); + + return dist(m_randomEngine); +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.h b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.h new file mode 100644 index 0000000000000000000000000000000000000000..c073fcf213faf12b8c75f2d61c4eb9332b0d888c --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.h @@ -0,0 +1,110 @@ +//-------------------------------------------------------------------------------------- +// SimpleInstancing.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "Shared.h" + +#include + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void ReplaceBufferContents(ID3D11Buffer* buffer, size_t bufferSize, const void* data); + void ResetSimulation(); + + float FloatRand(float lowerBound = -1.0f, float upperBound = 1.0f); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + std::unique_ptr m_batch; + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + //-------------------------------------------------------------------------------------- + // Sample Objects. + //-------------------------------------------------------------------------------------- + + // Instance vertex definition + struct Instance + { + DirectX::XMFLOAT4 quaternion; + DirectX::XMFLOAT4 positionAndScale; + }; + + // Light data structure (maps to constant buffer in pixel shader) + struct Lights + { + DirectX::XMFLOAT4 directional; + DirectX::XMFLOAT4 pointPositions[c_pointLightCount]; + DirectX::XMFLOAT4 pointColors[c_pointLightCount]; + }; + + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_instanceData; + Microsoft::WRL::ComPtr m_boxColors; + Microsoft::WRL::ComPtr m_vertexConstants; + Microsoft::WRL::ComPtr m_pixelConstants; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_pixelShader; + + struct aligned_deleter { void operator()(void* p) { _aligned_free(p); } }; + + std::unique_ptr m_CPUInstanceData; + std::unique_ptr m_rotationQuaternions; + std::unique_ptr m_velocities; + uint32_t m_usedInstanceCount; + + DirectX::XMFLOAT4X4 m_proj; + Lights m_lights; + float m_pitch; + float m_yaw; + + std::default_random_engine m_randomEngine; +}; diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.hlsli b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..8ed34c327427f03b94f384f59f23e32e4b22b65e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.hlsli @@ -0,0 +1,119 @@ +//-------------------------------------------------------------------------------------- +// SimpleInstancing.hlsli +// +// Simple shaders demonstrating how to perform instanced drawing. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "Shared.h" + +//-------------------------------------------------------------------------------------- +// Name: InstancingConstants +// Desc: Constant buffer containing clip-space transform. +//-------------------------------------------------------------------------------------- +cbuffer InstancingConstants +{ + float4x4 Clip; // Clip transform +}; + +//-------------------------------------------------------------------------------------- +// Name: Lights +// Desc: Constant buffer containing lighting information. +//-------------------------------------------------------------------------------------- +cbuffer Lights +{ + float4 Directional; + float4 PointPositions[ c_pointLightCount ]; + float4 PointColors[ c_pointLightCount ]; +}; + +//-------------------------------------------------------------------------------------- +// Name: InstancedVertex +// Desc: Structure containing vertex definition for instanced drawing. +// The incoming vertices arrive from 3 streams - one of which contains +// per-primitive information, the other two per-instance. +//-------------------------------------------------------------------------------------- +struct InstancedVertex +{ + float3 Position : POSITION; // Vertex position (per primitive) + float3 Normal : NORMAL; // Vertex normal (per primitive) + float4 InstRotation : I_ROTATION; // Orientation quaternion (per instance) + float4 InstPosScale : I_POSSCALE; // Position and scale (per instance) + float4 InstColor : I_COLOR; // Color (per instance) +}; + +//-------------------------------------------------------------------------------------- +// Name: Interpolants +// Desc: Interpolated values passed to the pixel shader. +//-------------------------------------------------------------------------------------- +struct Interpolants +{ + float4 Position : SV_POSITION; + float3 Normal : TEXCOORD0; + float4 Color : TEXCOORD1; + float3 WorldPos : TEXCOORD2; +}; + +//-------------------------------------------------------------------------------------- +// Name: RotateVectorByQuaternion +// Desc: Rotate a vector using a quaternion. +//-------------------------------------------------------------------------------------- +float3 RotateVectorByQuaternion( float4 Q, float3 V ) +{ + return V + 2.0f * cross( Q.xyz, cross( Q.xyz, V ) + Q.w * V ); +} + +//-------------------------------------------------------------------------------------- +// Name: VSMain() +// Desc: Vertex Shader main entrypoint. +//-------------------------------------------------------------------------------------- +Interpolants VSMain( InstancedVertex In ) +{ + Interpolants Out = ( Interpolants ) 0; + // Scale. + float3 position = In.Position * In.InstPosScale.w; + + // Rotate vertex position and normal based on instance quaternion... + position = RotateVectorByQuaternion( In.InstRotation, position ); + float3 normal = RotateVectorByQuaternion( In.InstRotation, In.Normal ); + + // Move to world space. + position += In.InstPosScale.xyz; + + // ...and clip. + Out.Position = mul( float4( position, 1 ), Clip ); + + // World space transform + Out.WorldPos = position; + + // Finally, output normal and color + Out.Normal = normal; + Out.Color = In.InstColor; + + return Out; +} + +//-------------------------------------------------------------------------------------- +// Name: PSMain() +// Desc: Pixel Shader main entrypoint. +//-------------------------------------------------------------------------------------- +float4 PSMain( Interpolants In ) : SV_Target +{ + float4 colorOut = 0; + + // Directional component: + colorOut = saturate( dot( In.Normal, Directional.xyz ) ) * In.Color * 0.5; + + for( uint i = 0; i < c_pointLightCount; ++i ) + { + float3 pointDirection = PointPositions[ i ].xyz - In.WorldPos; + float d = length( pointDirection ); + float attenuation = max( 0, 1.0f - ( dot( pointDirection, pointDirection ) / 500 ) ); + pointDirection = normalize( pointDirection ); + colorOut += saturate( dot( In.Normal, pointDirection ) ) * In.Color * PointColors[ i ] * attenuation; + } + + return colorOut + ( ( sign( In.Color.a ) * In.Color ) ); +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.sln b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.sln new file mode 100644 index 0000000000000000000000000000000000000000..5a3483fea267277640b0c2d12259ac1ca75923b0 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleInstancing", "SimpleInstancing.vcxproj", "{9F03E829-0682-4770-AB28-05AAA36FE7DB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Debug|Durango.ActiveCfg = Debug|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Debug|Durango.Build.0 = Debug|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Debug|Durango.Deploy.0 = Debug|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Profile|Durango.ActiveCfg = Profile|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Profile|Durango.Build.0 = Profile|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Profile|Durango.Deploy.0 = Profile|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Release|Durango.ActiveCfg = Release|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Release|Durango.Build.0 = Release|Durango + {9F03E829-0682-4770-AB28-05AAA36FE7DB}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.vcxproj b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..9ad6fbdf8a2dc7073ef471d4833b3d67af85fe79 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.vcxproj @@ -0,0 +1,250 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleInstancing + {9f03e829-0682-4770-ab28-05aaa36fe7db} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + PSMain + Pixel + PSMain + Pixel + PSMain + Pixel + + + Vertex + Vertex + Vertex + VSMain + VSMain + VSMain + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..470fd76b086d6ea300d49827945d046b0edf8ec0 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/SimpleInstancing.vcxproj.filters @@ -0,0 +1,97 @@ + + + + + f5e0da3a-9baa-48b5-84e5-4e3a14ed70cd + + + 69b04a34-c39b-44b6-9fec-b1f1c22cf1a9 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {65499f50-4b31-4fe6-8eb2-43535166b97e} + + + {c29b7256-4f67-4a29-af7a-dc90a851468f} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + Shaders + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Shaders + + + Shaders + + + + + Shaders + + + Assets + + + Assets + + + + Assets + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/StepTimer.h b/XDKSamples/IntroGraphics/SimpleInstancing/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/Telemetry.h b/XDKSamples/IntroGraphics/SimpleInstancing/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/VertexShader.hlsl b/XDKSamples/IntroGraphics/SimpleInstancing/VertexShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..80ea069ae44a3deec6ce1d78f189ca1ce763e7fa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/VertexShader.hlsl @@ -0,0 +1,2 @@ +// VertexShader.hlsl file to provide an MSBuild target for the SimpleInstancing vertex-shader entry point +#include "SimpleInstancing.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/pch.cpp b/XDKSamples/IntroGraphics/SimpleInstancing/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleInstancing/pch.h b/XDKSamples/IntroGraphics/SimpleInstancing/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..ee91ff260944826e9e727247f4b887f63a46b704 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing/pch.h @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SpriteBatch.h" +#include "SimpleMath.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleInstancing12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleInstancing12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Main.cpp b/XDKSamples/IntroGraphics/SimpleInstancing12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d95694a92fc18085180265d61a6200bd94c92439 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleInstancing12.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleInstancing12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..85d314fe299a6898626fa11356a35a3363bb4a61 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleInstancing12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleInstancing12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/PixelShader.hlsl b/XDKSamples/IntroGraphics/SimpleInstancing12/PixelShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..0cf6f23e525ebc82ff981e5a12cd1b52bfa90896 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/PixelShader.hlsl @@ -0,0 +1,2 @@ +// PixelShader.hlsl file to provide an MSBuild target for the SimpleInstancing pixel-shader entry point +#include "SimpleInstancing.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Readme.docx b/XDKSamples/IntroGraphics/SimpleInstancing12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..3c4223630bd0d1b7994950671b3b86e7cea5920c Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleInstancing12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Shared.h b/XDKSamples/IntroGraphics/SimpleInstancing12/Shared.h new file mode 100644 index 0000000000000000000000000000000000000000..2cd0992a0caa3edd1ed5fcee4f6eb5a4737fd433 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/Shared.h @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// Shared.h +// +// Shared declarations between shaders (HLSL) and C++ source. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +static const unsigned int c_pointLightCount = 25; diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing.hlsli b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..cf9d1479da8524c043bf35b46c7a8c6454da0ad0 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing.hlsli @@ -0,0 +1,128 @@ +//-------------------------------------------------------------------------------------- +// SimpleInstancing.hlsli +// +// Simple shaders demonstrating how to perform instanced drawing. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "Shared.h" + +#define rootSig "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT" \ + "| DENY_DOMAIN_SHADER_ROOT_ACCESS " \ + "| DENY_GEOMETRY_SHADER_ROOT_ACCESS " \ + "| DENY_HULL_SHADER_ROOT_ACCESS), " \ + "CBV(b0, space = 0, visibility=SHADER_VISIBILITY_VERTEX), " \ + "CBV(b0, space = 0, visibility=SHADER_VISIBILITY_PIXEL)" + +//-------------------------------------------------------------------------------------- +// Name: InstancingConstants +// Desc: Constant buffer containing clip-space transform. +//-------------------------------------------------------------------------------------- +cbuffer InstancingConstants +{ + float4x4 Clip; // Clip transform +}; + +//-------------------------------------------------------------------------------------- +// Name: Lights +// Desc: Constant buffer containing lighting information. +//-------------------------------------------------------------------------------------- +cbuffer Lights +{ + float4 Directional; + float4 PointPositions[ c_pointLightCount ]; + float4 PointColors[ c_pointLightCount ]; +}; + +//-------------------------------------------------------------------------------------- +// Name: InstancedVertex +// Desc: Structure containing vertex definition for instanced drawing. +// The incoming vertices arrive from 3 streams - one of which contains +// per-primitive information, the other two per-instance. +//-------------------------------------------------------------------------------------- +struct InstancedVertex +{ + float3 Position : POSITION; // Vertex position (per primitive) + float3 Normal : NORMAL; // Vertex normal (per primitive) + float4 InstRotation : I_ROTATION; // Orientation quaternion (per instance) + float4 InstPosScale : I_POSSCALE; // Position and scale (per instance) + float4 InstColor : I_COLOR; // Color (per instance) +}; + +//-------------------------------------------------------------------------------------- +// Name: Interpolants +// Desc: Interpolated values passed to the pixel shader. +//-------------------------------------------------------------------------------------- +struct Interpolants +{ + float4 Position : SV_POSITION; + float3 Normal : TEXCOORD0; + float4 Color : TEXCOORD1; + float3 WorldPos : TEXCOORD2; +}; + +//-------------------------------------------------------------------------------------- +// Name: RotateVectorByQuaternion +// Desc: Rotate a vector using a quaternion. +//-------------------------------------------------------------------------------------- +float3 RotateVectorByQuaternion( float4 Q, float3 V ) +{ + return V + 2.0f * cross( Q.xyz, cross( Q.xyz, V ) + Q.w * V ); +} + +//-------------------------------------------------------------------------------------- +// Name: VSMain() +// Desc: Vertex Shader main entrypoint. +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +Interpolants VSMain( InstancedVertex In ) +{ + Interpolants Out = ( Interpolants ) 0; + // Scale. + float3 position = In.Position * In.InstPosScale.w; + + // Rotate vertex position and normal based on instance quaternion... + position = RotateVectorByQuaternion( In.InstRotation, position ); + float3 normal = RotateVectorByQuaternion( In.InstRotation, In.Normal ); + + // Move to world space. + position += In.InstPosScale.xyz; + + // ...and clip. + Out.Position = mul( float4( position, 1 ), Clip ); + + // World space transform + Out.WorldPos = position; + + // Finally, output normal and color + Out.Normal = normal; + Out.Color = In.InstColor; + + return Out; +} + +//-------------------------------------------------------------------------------------- +// Name: PSMain() +// Desc: Pixel Shader main entrypoint. +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +float4 PSMain( Interpolants In ) : SV_Target +{ + float4 colorOut = 0; + + // Directional component: + colorOut = saturate( dot( In.Normal, Directional.xyz ) ) * In.Color * 0.5; + + for( uint i = 0; i < c_pointLightCount; ++i ) + { + float3 pointDirection = PointPositions[ i ].xyz - In.WorldPos; + float d = length( pointDirection ); + float attenuation = max( 0, 1.0f - ( dot( pointDirection, pointDirection ) / 500 ) ); + pointDirection = normalize( pointDirection ); + colorOut += saturate( dot( In.Normal, pointDirection ) ) * In.Color * PointColors[ i ] * attenuation; + } + + return colorOut + ( ( sign( In.Color.a ) * In.Color ) ); +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.cpp b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b734a3e6f051b7fd92c5fd7582cb1749b68421d9 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.cpp @@ -0,0 +1,708 @@ +//-------------------------------------------------------------------------------------- +// SimpleInstancing12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleInstancing12.h" + +#include "ATGColors.h" +#include "ControllerFont.h" +#include "ReadData.h" + +#pragma warning(disable : 4238) + +using namespace DirectX; +using namespace DirectX::PackedVector; + +using Microsoft::WRL::ComPtr; + +namespace +{ + //-------------------------------------------------------------------------------------- + // Constants + //-------------------------------------------------------------------------------------- + const uint32_t c_maxInstances = 20000; + const uint32_t c_startInstanceCount = 5000; + const uint32_t c_minInstanceCount = 1000; + const float c_boxBounds = 60.0f; + const size_t c_cubeIndexCount = 36; + const float c_velocityMultiplier = 500.0f; + + //-------------------------------------------------------------------------------------- + // Cube vertex definition + //-------------------------------------------------------------------------------------- + struct Vertex + { + XMFLOAT3 pos; + XMFLOAT3 norm; + }; +} + +Sample::Sample() : + m_frame(0), + m_mappedInstanceData(nullptr), + m_instanceDataGpuAddr(0), + m_usedInstanceCount(c_startInstanceCount), + m_lights{}, + m_pitch(0.0f), + m_yaw(0.0f) +{ + XMStoreFloat4x4(&m_proj, XMMatrixIdentity()); + + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::ButtonState::PRESSED) + { + ResetSimulation(); + } + + if (m_gamePadButtons.rightShoulder == GamePad::ButtonStateTracker::ButtonState::PRESSED) + { + m_usedInstanceCount = std::min(c_maxInstances, m_usedInstanceCount + 1000); + } + else if (m_gamePadButtons.leftShoulder == GamePad::ButtonStateTracker::ButtonState::PRESSED) + { + m_usedInstanceCount = std::max(c_minInstanceCount, m_usedInstanceCount - 1000); + } + + if (pad.IsLeftStickPressed()) + { + m_yaw = m_pitch = 0.f; + } + else + { + m_yaw += pad.thumbSticks.leftX * 0.1f; + m_pitch += pad.thumbSticks.leftY * 0.1f; + } + } + else + { + m_gamePadButtons.Reset(); + } + + // Limit to avoid looking directly up or down + float limit = XM_PI / 2.0f - 0.01f; + m_pitch = std::max(-limit, m_pitch); + m_pitch = std::min(+limit, m_pitch); + + if (m_yaw > XM_PI) + { + m_yaw -= XM_PI * 2.f; + } + else if (m_yaw < -XM_PI) + { + m_yaw += XM_PI * 2.f; + } + + XMVECTOR lookAt = XMVectorSet( + sinf(m_yaw), + m_pitch, + cosf(m_yaw), + 0); + + // Update transforms. + XMMATRIX camera = XMMatrixLookAtLH(g_XMZero, lookAt, g_XMIdentityR1); + XMMATRIX proj = XMLoadFloat4x4(&m_proj); + XMMATRIX clip = XMMatrixTranspose(XMMatrixMultiply(camera, proj)); + XMStoreFloat4x4( &m_clip, clip); + + // Update instance data for the next frame. + for (size_t i = 1; i < m_usedInstanceCount; ++i) + { + // Update positions... + float velocityMultiplier = i <= c_pointLightCount ? 5.0f * c_velocityMultiplier : c_velocityMultiplier; + XMVECTOR position = XMLoadFloat4(&m_CPUInstanceData[i].positionAndScale); + position += m_velocities[i] * elapsedTime * velocityMultiplier; + XMStoreFloat4(&m_CPUInstanceData[i].positionAndScale, position); + + float X = m_CPUInstanceData[i].positionAndScale.x; + float Y = m_CPUInstanceData[i].positionAndScale.y; + float Z = m_CPUInstanceData[i].positionAndScale.z; + + bool bounce = false; + + // If an instance pops out of bounds in any dimension, reverse velocity in that dimension... + if (X < -c_boxBounds || X > c_boxBounds) + { + m_velocities[i] *= XMVectorSet(-1.0f, 1.0f, 1.0f, 1.0f); + bounce = true; + } + if (Y < -c_boxBounds || Y > c_boxBounds) + { + m_velocities[i] *= XMVectorSet(1.0f, -1.0f, 1.0f, 1.0f); + bounce = true; + } + if (Z < -c_boxBounds || Z > c_boxBounds) + { + m_velocities[i] *= XMVectorSet(1.0f, 1.0f, -1.0f, 1.0f); + bounce = true; + } + + // Apply bounce here. + if (bounce) + { + position = XMLoadFloat4(&m_CPUInstanceData[i].positionAndScale); + position += m_velocities[i] * elapsedTime * c_velocityMultiplier; + XMStoreFloat4(&m_CPUInstanceData[i].positionAndScale, position); + } + + // Set up point light info. + if (i <= c_pointLightCount) + { + m_lights.pointPositions[i - 1] = m_CPUInstanceData[i].positionAndScale; + } + + XMVECTOR q = XMLoadFloat4(&m_CPUInstanceData[i].quaternion); + q = XMQuaternionNormalizeEst(XMQuaternionMultiply(m_rotationQuaternions[i], q)); + XMStoreFloat4(&m_CPUInstanceData[i].quaternion, q); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Check to see if the GPU is keeping up + int frameIdx = m_deviceResources->GetCurrentFrameIndex(); + int numBackBuffers = m_deviceResources->GetBackBufferCount(); + uint64_t completedValue = m_fence->GetCompletedValue(); + if ((frameIdx > completedValue) // if frame index is reset to zero it may temporarily be smaller than the last GPU signal + && (frameIdx - completedValue > numBackBuffers)) + { + // GPU not caught up, wait for at least one available frame + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(frameIdx - numBackBuffers, m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(m_pipelineState.Get()); + + // We use the DirectX Tool Kit helper for managing constants memory + // (see SimpleLighting12 for how to provide constants without this helper) + auto vertexConstants = m_graphicsMemory->AllocateConstant(m_clip); + auto pixelConstants = m_graphicsMemory->AllocateConstant(m_lights); + + commandList->SetGraphicsRootConstantBufferView(0, vertexConstants.GpuAddress()); + commandList->SetGraphicsRootConstantBufferView(1, pixelConstants.GpuAddress()); + + // Set necessary state. + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // Provide per-frame instance data + int instanceIdx = (frameIdx % numBackBuffers); + int frameOffset = (c_maxInstances * sizeof(Instance)) * instanceIdx; + + memcpy(m_mappedInstanceData + frameOffset, m_CPUInstanceData.get(), sizeof(Instance) * m_usedInstanceCount); + + m_vertexBufferView[1].BufferLocation = m_instanceDataGpuAddr + frameOffset; + m_vertexBufferView[1].StrideInBytes = sizeof(Instance); + m_vertexBufferView[1].SizeInBytes = sizeof(Instance) * m_usedInstanceCount; + + // Set up the vertex buffers. We have 3 streams: + // Stream 1 contains per-primitive vertices defining the cubes. + // Stream 2 contains the per-instance data for scale, position and orientation + // Stream 3 contains the per-instance data for color. + commandList->IASetVertexBuffers(0, _countof(m_vertexBufferView), m_vertexBufferView); + + // The per-instance data is referenced by index... + commandList->IASetIndexBuffer(&m_indexBufferView); + + // Draw the entire scene... + commandList->DrawIndexedInstanced(c_cubeIndexCount, m_usedInstanceCount, 0, 0, 0); + + // Draw UI. + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + m_batch->Begin(commandList); + + wchar_t str[32] = {}; + swprintf_s(str, L"Instancing count: %u", m_usedInstanceCount); + m_smallFont->DrawString(m_batch.get(), str, XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::White); + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + L"[LThumb] Rotate [A] Reset [LB]/[RB] Change instance count [View] Exit", + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + + // GPU will signal an increasing value each frame + m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), frameIdx); + + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + // Use linear clear color for gamma-correct rendering. + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + m_resourceDescriptors = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); + + ResourceUploadBatch resourceUpload(device); + + resourceUpload.Begin(); + + { + RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + + SpriteBatchPipelineStateDescription pd(rtState); + + m_batch = std::make_unique(device, resourceUpload, pd); + } + + // Create a root signature + { + CD3DX12_ROOT_PARAMETER rootParameters[2] = {}; + rootParameters[0].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_VERTEX); + rootParameters[1].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_PIXEL); + + // Allow input layout and deny uneccessary access to certain pipeline stages. + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + 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; + + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags); + + ComPtr signature; + ComPtr error; + DX::ThrowIfFailed( + D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create the pipeline state, which includes loading shaders. + auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); + + auto pixelShaderBlob = DX::ReadData(L"PixelShader.cso"); + + static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[] = + { + // SemanticName SemanticIndex Format InputSlot AlignedByteOffset InputSlotClass InstanceDataStepRate + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, // Vertex local position + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, // Vertex normal + { "I_ROTATION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }, // Instance rotation quaternion + { "I_POSSCALE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }, // Instance position and scale (scale in "w") + { "I_COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 2, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }, // Instance color + }; + + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; + psoDesc.PS = { pixelShaderBlob.data(), pixelShaderBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_GRAPHICS_PPV_ARGS(m_pipelineState.ReleaseAndGetAddressOf()))); + + // Create and initialize the vertex buffer defining a cube. + { + static const Vertex s_vertexData[] = + { + { XMFLOAT3(-1, -1, -1), XMFLOAT3(0, 0, -1) }, + { XMFLOAT3( 1, -1, -1), XMFLOAT3(0, 0, -1) }, + { XMFLOAT3( 1, 1, -1), XMFLOAT3(0, 0, -1) }, + { XMFLOAT3(-1, 1, -1), XMFLOAT3(0, 0, -1) }, // Z negative face + + { XMFLOAT3( 1, -1, 1), XMFLOAT3(0, 0, 1) }, + { XMFLOAT3(-1, -1, 1), XMFLOAT3(0, 0, 1) }, + { XMFLOAT3(-1, 1, 1), XMFLOAT3(0, 0, 1) }, + { XMFLOAT3( 1, 1, 1), XMFLOAT3(0, 0, 1) }, // Z Positive face + + { XMFLOAT3(-1, -1, -1), XMFLOAT3(-1, 0, 0) }, + { XMFLOAT3(-1, 1, -1), XMFLOAT3(-1, 0, 0) }, + { XMFLOAT3(-1, 1, 1), XMFLOAT3(-1, 0, 0) }, + { XMFLOAT3(-1, -1, 1), XMFLOAT3(-1, 0, 0) }, // X negative face + + { XMFLOAT3( 1, 1, -1), XMFLOAT3( 1, 0, 0) }, + { XMFLOAT3( 1, -1, -1), XMFLOAT3( 1, 0, 0) }, + { XMFLOAT3( 1, -1, 1), XMFLOAT3( 1, 0, 0) }, + { XMFLOAT3( 1, 1, 1), XMFLOAT3( 1, 0, 0) }, // X Positive face + + { XMFLOAT3(-1, -1, 1), XMFLOAT3(0, -1, 0) }, + { XMFLOAT3( 1, -1, 1), XMFLOAT3(0, -1, 0) }, + { XMFLOAT3( 1, -1, -1), XMFLOAT3(0, -1, 0) }, + { XMFLOAT3(-1, -1, -1), XMFLOAT3(0, -1, 0) }, // Y negative face + + { XMFLOAT3( 1, 1, 1), XMFLOAT3(0, 1, 0) }, + { XMFLOAT3(-1, 1, 1), XMFLOAT3(0, 1, 0) }, + { XMFLOAT3(-1, 1, -1), XMFLOAT3(0, 1, 0) }, + { XMFLOAT3( 1, 1, -1), XMFLOAT3(0, 1, 0) }, // Y Positive face + }; + + // Note: using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are very few verts to actually transfer. + DX::ThrowIfFailed( + device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_vertexData)), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_vertexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the triangle data to the vertex buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_vertexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, s_vertexData, sizeof(s_vertexData)); + m_vertexBuffer->Unmap(0, nullptr); + + // Initialize the vertex buffer view. + m_vertexBufferView[0].BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); + m_vertexBufferView[0].StrideInBytes = sizeof(Vertex); + m_vertexBufferView[0].SizeInBytes = sizeof(s_vertexData); + } + + // Create vertex buffer memory for per-instance data. + { + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + size_t cbSize = c_maxInstances * m_deviceResources->GetBackBufferCount() * sizeof(Instance); + + const D3D12_RESOURCE_DESC instanceBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(cbSize); + DX::ThrowIfFailed(device->CreateCommittedResource( + &uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &instanceBufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_instanceData.ReleaseAndGetAddressOf()))); + + DX::ThrowIfFailed(m_instanceData->Map(0, nullptr, reinterpret_cast< void** >(&m_mappedInstanceData))); + + m_instanceDataGpuAddr = m_instanceData->GetGPUVirtualAddress(); + } + + // Create a static vertex buffer with color data. + { + static const XMVECTORF32 s_bigCubeColor = { 1.f, 1.f, 1.f, 0.f }; + uint32_t colors[c_maxInstances]; + colors[0] = XMCOLOR(s_bigCubeColor); + for (uint32_t i = 1; i < c_maxInstances; ++i) + { + if (i <= c_pointLightCount) + { + m_lights.pointColors[i - 1] = XMFLOAT4(FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), 1.0f); + colors[i] = XMCOLOR(m_lights.pointColors[i - 1].x, m_lights.pointColors[i - 1].y, m_lights.pointColors[i - 1].z, 1.f); + } + else + { + colors[i] = XMCOLOR(FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), FloatRand(0.25f, 1.0f), 0.f); + } + } + + DX::ThrowIfFailed( + device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(uint32_t) * c_maxInstances), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_boxColors.ReleaseAndGetAddressOf()))); + + // Copy the color data to the vertex buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_boxColors->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, colors, sizeof(uint32_t) * c_maxInstances); + m_boxColors->Unmap(0, nullptr); + + // Initialize the vertex buffer view. + m_vertexBufferView[2].BufferLocation = m_boxColors->GetGPUVirtualAddress(); + m_vertexBufferView[2].StrideInBytes = sizeof(uint32_t); + m_vertexBufferView[2].SizeInBytes = sizeof(uint32_t) * c_maxInstances; + } + + // Create and initialize the index buffer for the cube geometry. + { + static const uint16_t s_indexData[] = + { + 0, 2, 1, + 0, 3, 2, + 4, 6, 5, + 4, 7, 6, + 8, 10, 9, + 8, 11, 10, + 12, 14, 13, + 12, 15, 14, + 16, 18, 17, + 16, 19, 18, + 20, 22, 21, + 20, 23, 22, + }; + + // See note above + DX::ThrowIfFailed( + device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_indexData)), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_indexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the data to the index buffer. + uint8_t* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_indexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, s_indexData, sizeof(s_indexData)); + m_indexBuffer->Unmap(0, nullptr); + + // Initialize the index buffer view. + m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); + m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; + m_indexBufferView.SizeInBytes = sizeof(s_indexData); + } + + m_CPUInstanceData.reset(new Instance[c_maxInstances]); + m_rotationQuaternions.reset(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * c_maxInstances, 16))); + m_velocities.reset(reinterpret_cast(_aligned_malloc(sizeof(XMVECTOR) * c_maxInstances, 16))); + + // Set up the position and scale for the container box. Scale is negative to turn the box inside-out + // (this effectively reverses the normals and backface culling). + // Scale the outside box to slightly larger than our scene boundary, so bouncing boxes never actually clip it. + m_CPUInstanceData[0].positionAndScale = XMFLOAT4(0.0f, 0.0f, 0.0f, -(c_boxBounds + 5)); + m_CPUInstanceData[0].quaternion = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); + + // Initialize the directional light. + XMStoreFloat4(&m_lights.directional, XMVector3Normalize(XMVectorSet(1.0f, 4.0f, -2.0f, 0))); + + // Initialize the positions/state of all the cubes in the scene. + ResetSimulation(); + + // Wait until assets have been uploaded to the GPU. + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + + // Create a fence for synchronizing between the CPU and the GPU + DX::ThrowIfFailed(device->CreateFence(m_deviceResources->GetCurrentFrameIndex(), D3D12_FENCE_FLAG_NONE, + IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + + // Start off the fence with the current frame index + uint64_t currentIdx = m_deviceResources->GetCurrentFrameIndex(); + m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), currentIdx); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + // Initialize the projection matrix. + auto size = m_deviceResources->GetOutputSize(); + + auto device = m_deviceResources->GetD3DDevice(); + + ResourceUploadBatch resourceUpload(device); + + resourceUpload.Begin(); + + m_smallFont = std::make_unique(device, resourceUpload, + (size.bottom > 1080) ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::TextFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::TextFont)); + + m_ctrlFont = std::make_unique(device, resourceUpload, + (size.bottom > 1080) ? L"XboxOneControllerLegend.spritefont" : L"XboxOneControllerLegendSmall.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::ControllerFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::ControllerFont)); + + // Wait until assets have been uploaded to the GPU. + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + + XMMATRIX proj = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.1f, 500.0f); + XMStoreFloat4x4(&m_proj, proj); + + // Set the viewport for our SpriteBatch. + m_batch->SetViewport(m_deviceResources->GetScreenViewport()); +} +#pragma endregion + +void Sample::ResetSimulation() +{ + // Reset positions to starting point, and orientations to identity. + // Note that instance 0 is the scene bounding box, and the position, orientation and scale are static (i.e. never update). + for (size_t i = 1; i < c_maxInstances; ++i) + { + m_CPUInstanceData[i].positionAndScale = XMFLOAT4(0.0f, 0.0f, c_boxBounds / 2.0f, FloatRand(0.1f, 0.4f)); + m_CPUInstanceData[i].quaternion = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); + + // For the first c_pointLightCount in the updated array, we scale up by a small factor so they stand out. + if (i <= c_pointLightCount) + { + m_CPUInstanceData[i].positionAndScale.w = 1.53f; + m_lights.pointPositions[i - 1] = m_CPUInstanceData[i].positionAndScale; + } + + // Apply a random spin to each instance. + m_rotationQuaternions[i] = XMQuaternionRotationAxis(XMVector3Normalize(XMVectorSet(FloatRand(), FloatRand(), FloatRand(), 0)), FloatRand(0.001f, 0.1f)); + + // ...and a random velocity. + m_velocities[i] = XMVectorSet(FloatRand(-0.01f, 0.01f), FloatRand(-0.01f, 0.01f), FloatRand(-0.01f, 0.01f), 0); + } +} + +inline float Sample::FloatRand(float lowerBound, float upperBound) +{ + if (lowerBound == upperBound) + return lowerBound; + + std::uniform_real_distribution dist(lowerBound, upperBound); + + return dist(m_randomEngine); +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.h b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.h new file mode 100644 index 0000000000000000000000000000000000000000..e314948de2b0ec3ac2651a6b3ce6bb52a60abe65 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.h @@ -0,0 +1,125 @@ +//-------------------------------------------------------------------------------------- +// SimpleInstancing12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "Shared.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void ResetSimulation(); + float FloatRand(float lowerBound = -1.0f, float upperBound = 1.0f); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_resourceDescriptors; + std::unique_ptr m_batch; + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + enum Descriptors + { + TextFont, + ControllerFont, + Count + }; + + //-------------------------------------------------------------------------------------- + // Sample Objects. + //-------------------------------------------------------------------------------------- + + // Instance vertex definition + struct Instance + { + DirectX::XMFLOAT4 quaternion; + DirectX::XMFLOAT4 positionAndScale; + }; + + // Light data structure (maps to constant buffer in pixel shader) + struct Lights + { + DirectX::XMFLOAT4 directional; + DirectX::XMFLOAT4 pointPositions[c_pointLightCount]; + DirectX::XMFLOAT4 pointColors[c_pointLightCount]; + }; + + // Direct3D 12 pipeline objects. + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_pipelineState; + + // Direct3D 12 resources. + Microsoft::WRL::ComPtr m_vertexBuffer; + D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView[3]; + Microsoft::WRL::ComPtr m_indexBuffer; + D3D12_INDEX_BUFFER_VIEW m_indexBufferView; + Microsoft::WRL::ComPtr m_boxColors; + + Microsoft::WRL::ComPtr m_instanceData; + uint8_t* m_mappedInstanceData; + D3D12_GPU_VIRTUAL_ADDRESS m_instanceDataGpuAddr; + + // A synchronization fence and an event. These members will be used + // to synchronize the CPU with the GPU so that there will be no + // contention for the instance data. + Microsoft::WRL::ComPtr m_fence; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + struct aligned_deleter { void operator()(void* p) { _aligned_free(p); } }; + + std::unique_ptr m_CPUInstanceData; + std::unique_ptr m_rotationQuaternions; + std::unique_ptr m_velocities; + uint32_t m_usedInstanceCount; + + DirectX::XMFLOAT4X4 m_proj; + DirectX::XMFLOAT4X4 m_clip; + Lights m_lights; + float m_pitch; + float m_yaw; + + std::default_random_engine m_randomEngine; +}; diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.sln b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.sln new file mode 100644 index 0000000000000000000000000000000000000000..94be2799c4d29bf58d415553b8986f54d780e2f8 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleInstancing12", "SimpleInstancing12.vcxproj", "{A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}" + ProjectSection(ProjectDependencies) = postProject + {0EE6C863-556C-4815-8BFF-A5A0B25A948F} = {0EE6C863-556C-4815-8BFF-A5A0B25A948F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Debug|Durango.ActiveCfg = Debug|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Debug|Durango.Build.0 = Debug|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Debug|Durango.Deploy.0 = Debug|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Profile|Durango.ActiveCfg = Profile|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Profile|Durango.Build.0 = Profile|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Profile|Durango.Deploy.0 = Profile|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Release|Durango.ActiveCfg = Release|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Release|Durango.Build.0 = Release|Durango + {A090FF7B-9BCA-46D3-B6E2-06AF8C9D9026}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.vcxproj b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6aaa34a7e568dc5e0c1f5f1ebf800e70ddaa88f8 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.vcxproj @@ -0,0 +1,256 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleInstancing12 + {a090ff7b-9bca-46d3-b6e2-06af8c9d9026} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + PSMain + Pixel + PSMain + Pixel + PSMain + Pixel + 5.0 + 5.0 + 5.0 + + + VSMain + Vertex + VSMain + Vertex + VSMain + Vertex + 5.0 + 5.0 + 5.0 + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..e54c2ecfdc1102ca18931a64275ace3b4b49ab8c --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/SimpleInstancing12.vcxproj.filters @@ -0,0 +1,97 @@ + + + + + 67837001-282b-4e25-b61c-b80e7a7881d4 + + + 79d2aaf2-d652-40a4-a7b8-bc84fd1a62e1 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {33e038f3-3c9c-47dc-ad75-c4b768ae7bfc} + + + {eb377b19-da7a-46eb-93a1-4eb398650615} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + Shaders + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Shaders + + + Shaders + + + + + Shaders + + + + Assets + + + Assets + + + Assets + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleInstancing12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleInstancing12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/VertexShader.hlsl b/XDKSamples/IntroGraphics/SimpleInstancing12/VertexShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..80ea069ae44a3deec6ce1d78f189ca1ce763e7fa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/VertexShader.hlsl @@ -0,0 +1,2 @@ +// VertexShader.hlsl file to provide an MSBuild target for the SimpleInstancing vertex-shader entry point +#include "SimpleInstancing.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/pch.cpp b/XDKSamples/IntroGraphics/SimpleInstancing12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleInstancing12/pch.h b/XDKSamples/IntroGraphics/SimpleInstancing12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..65af63eedb23812022214c5d84c67cd6189e4379 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleInstancing12/pch.h @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "DescriptorHeap.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "ResourceUploadBatch.h" +#include "SpriteBatch.h" +#include "SimpleMath.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleLighting/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleLighting/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleLighting/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleLighting/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleLighting/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleLighting/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleLighting/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/LambertPS.hlsl b/XDKSamples/IntroGraphics/SimpleLighting/LambertPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..0458f99b45ca7437238923bedec61a8ab83ad64e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/LambertPS.hlsl @@ -0,0 +1,2 @@ +// LambertPS.hlsl file to provide an MSBuild target for the LambertPS pixel-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Main.cpp b/XDKSamples/IntroGraphics/SimpleLighting/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86aef0292754eb6c4da4635b4a02117dd7be0e04 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleLighting.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleLighting/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..963fb4233d28992be0ee9b4a1fdc334b96d5a181 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleLighting + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleLighting + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Readme.docx b/XDKSamples/IntroGraphics/SimpleLighting/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..d6b7f78b852280c33029e4d2b3342859aec0a353 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.cpp b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9901a4fab570e96a375aa42068d661ed9f859c30 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.cpp @@ -0,0 +1,418 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleLighting.h" +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + struct Vertex + { + XMFLOAT3 pos; + XMFLOAT3 normal; + }; + + struct ConstantBuffer + { + XMMATRIX worldMatrix; + XMMATRIX viewMatrix; + XMMATRIX projectionMatrix; + XMVECTOR lightDir[2]; + XMVECTOR lightColor[2]; + XMVECTOR outputColor; + }; + + static_assert((sizeof(ConstantBuffer) % 16) == 0, "Constant buffer must always be 16-byte aligned"); +} + +Sample::Sample() : + m_frame(0), + m_curRotationAngleRad(0.0f) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + // Update the rotation constant + m_curRotationAngleRad += elapsedTime / 3.f; + if (m_curRotationAngleRad >= XM_2PI) + { + m_curRotationAngleRad -= XM_2PI; + } + + // Rotate the cube around the origin + XMStoreFloat4x4(&m_worldMatrix, XMMatrixRotationY(m_curRotationAngleRad)); + + // Setup our lighting parameters + m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); + m_lightDirs[1] = XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f); + + m_lightColors[0] = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); + m_lightColors[1] = XMFLOAT4(0.5f, 0.0f, 0.0f, 1.0f); + + // Rotate the second light around the origin + XMMATRIX rotate = XMMatrixRotationY(-2.0f * m_curRotationAngleRad); + XMVECTOR lightDir = XMLoadFloat4(&m_lightDirs[1]); + lightDir = XMVector3Transform(lightDir, rotate); + XMStoreFloat4(&m_lightDirs[1], lightDir); + + // Handle controller input for exit + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Set the vertex buffer + UINT stride = sizeof(Vertex); + UINT offset = 0; + context->IASetVertexBuffers(0, 1, m_vertexBuffer.GetAddressOf(), &stride, &offset); + + // Set the index buffer + context->IASetIndexBuffer(m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0); + + // Set the input layout + context->IASetInputLayout(m_inputLayout.Get()); + + // Set the primitive toplogy + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // Set the per-frame constants + ConstantBuffer sceneParameters = {}; + + // Shaders compiled with default row-major matrices + sceneParameters.worldMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_worldMatrix)); + sceneParameters.viewMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_viewMatrix)); + sceneParameters.projectionMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_projectionMatrix)); + + sceneParameters.lightDir[0] = XMLoadFloat4(&m_lightDirs[0]); + sceneParameters.lightDir[1] = XMLoadFloat4(&m_lightDirs[1]); + sceneParameters.lightColor[0] = XMLoadFloat4(&m_lightColors[0]); + sceneParameters.lightColor[1] = XMLoadFloat4(&m_lightColors[1]); + sceneParameters.outputColor = XMLoadFloat4(&m_outputColor); + + { + D3D11_MAPPED_SUBRESOURCE mapped; + DX::ThrowIfFailed(context->Map(m_constantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); + memcpy(mapped.pData, &sceneParameters, sizeof(ConstantBuffer)); + context->Unmap(m_constantBuffer.Get(), 0); + } + + // Render the cube + context->VSSetShader(m_vertexShader.Get(), nullptr, 0); + + // Vertex shader needs view and projection matrices to perform vertex transform + context->VSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf()); + + context->PSSetShader(m_pixelShader.Get(), nullptr, 0); + + // Pixel shader needs light-direction vectors to perform per-pixel lighting + context->PSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf()); + context->DrawIndexed(36, 0, 0); + + // Render each light + for (int m = 0; m < 2; ++m) + { + XMMATRIX lightMatrix = XMMatrixTranslationFromVector(5.0f * sceneParameters.lightDir[m]); + XMMATRIX lightScaleMatrix = XMMatrixScaling(0.2f, 0.2f, 0.2f); + lightMatrix = lightScaleMatrix * lightMatrix; + + // Update the world variable to reflect the current light + sceneParameters.worldMatrix = XMMatrixTranspose(lightMatrix); + sceneParameters.outputColor = sceneParameters.lightColor[m]; + + { + D3D11_MAPPED_SUBRESOURCE mapped; + DX::ThrowIfFailed(context->Map(m_constantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); + memcpy(mapped.pData, &sceneParameters, sizeof(ConstantBuffer)); + context->Unmap(m_constantBuffer.Get(), 0); + } + + context->VSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf()); + context->PSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf()); + + context->PSSetShader(m_pixelShaderSolid.Get(), nullptr, 0); + context->DrawIndexed(36, 0, 0); + } + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + // Use linear clear color for gamma-correct rendering + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + // Load and create shaders + { + auto blob = DX::ReadData(L"TriangleVS.cso"); + + DX::ThrowIfFailed( + device->CreateVertexShader(blob.data(), blob.size(), + nullptr, m_vertexShader.ReleaseAndGetAddressOf())); + + // Create the input layout + const D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + DX::ThrowIfFailed( + device->CreateInputLayout(inputElementDesc, _countof(inputElementDesc), + blob.data(), blob.size(), + m_inputLayout.ReleaseAndGetAddressOf())); + } + + { + auto blob = DX::ReadData(L"LambertPS.cso"); + + DX::ThrowIfFailed( + device->CreatePixelShader(blob.data(), blob.size(), + nullptr, m_pixelShader.ReleaseAndGetAddressOf())); + } + + { + auto blob = DX::ReadData(L"SolidColorPS.cso"); + + DX::ThrowIfFailed( + device->CreatePixelShader(blob.data(), blob.size(), + nullptr, m_pixelShaderSolid.ReleaseAndGetAddressOf())); + } + + // Create and initialize the vertex buffer + { + static const Vertex vertices[] = + { + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + }; + + CD3D11_BUFFER_DESC bufferDesc(sizeof(Vertex) * _countof(vertices), D3D11_BIND_VERTEX_BUFFER); + bufferDesc.StructureByteStride = sizeof(Vertex); + + D3D11_SUBRESOURCE_DATA initData = { vertices, 0, 0 }; + DX::ThrowIfFailed(device->CreateBuffer(&bufferDesc, &initData, m_vertexBuffer.ReleaseAndGetAddressOf())); + } + + // Create and initialize the index buffer + { + static const uint16_t indices[] = + { + 3,1,0, + 2,1,3, + + 6,4,5, + 7,4,6, + + 11,9,8, + 10,9,11, + + 14,12,13, + 15,12,14, + + 19,17,16, + 18,17,19, + + 22,20,21, + 23,20,22 + }; + CD3D11_BUFFER_DESC bufferDesc(sizeof(uint16_t) * _countof(indices), D3D11_BIND_INDEX_BUFFER); + bufferDesc.StructureByteStride = sizeof(uint16_t); + + D3D11_SUBRESOURCE_DATA initData = { indices, 0, 0 }; + DX::ThrowIfFailed(device->CreateBuffer(&bufferDesc, &initData, m_indexBuffer.ReleaseAndGetAddressOf())); + } + + // Create the constant buffer + { + CD3D11_BUFFER_DESC bufferDesc(sizeof(ConstantBuffer), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + DX::ThrowIfFailed(device->CreateBuffer(&bufferDesc, nullptr, m_constantBuffer.ReleaseAndGetAddressOf())); + } + + // Initialize the world matrix + XMStoreFloat4x4(&m_worldMatrix, XMMatrixIdentity()); + + // Initialize the view matrix + static const XMVECTORF32 c_eye = { 0.0f, 4.0f, -10.0f, 0.0f }; + static const XMVECTORF32 c_at = { 0.0f, 1.0f, 0.0f, 0.0f }; + static const XMVECTORF32 c_up = { 0.0f, 1.0f, 0.0f, 0.0 }; + XMStoreFloat4x4(&m_viewMatrix, XMMatrixLookAtLH(c_eye, c_at, c_up)); + + // Initialize the lighting parameters + m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); + m_lightDirs[1] = XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f); + + m_lightColors[0] = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); + m_lightColors[1] = XMFLOAT4(0.5f, 0.0f, 0.0f, 1.0f); + + // Initialize the scene output color + m_outputColor = XMFLOAT4(0, 0, 0, 0); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + // Initialize the projection matrix + auto size = m_deviceResources->GetOutputSize(); + XMMATRIX projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.01f, 100.0f); + XMStoreFloat4x4(&m_projectionMatrix, projection); + +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.h b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.h new file mode 100644 index 0000000000000000000000000000000000000000..e97efe20077183afe46ca65e5e77218a05fc405e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.h @@ -0,0 +1,78 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Sample Objects + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_constantBuffer; + + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_pixelShader; + Microsoft::WRL::ComPtr m_pixelShaderSolid; + + // Scene constants, updated per-frame + float m_curRotationAngleRad; + + // These computed values will be loaded into a ConstantBuffer + // during Render + DirectX::XMFLOAT4X4 m_worldMatrix; + DirectX::XMFLOAT4X4 m_viewMatrix; + DirectX::XMFLOAT4X4 m_projectionMatrix; + DirectX::XMFLOAT4 m_lightDirs[2]; + DirectX::XMFLOAT4 m_lightColors[2]; + DirectX::XMFLOAT4 m_outputColor; +}; diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.hlsli b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..337019e468e51dab6c05f4e5d6e923d50f547819 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.hlsli @@ -0,0 +1,80 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting.hlsl +// +// Shader demonstrating Lambertian lighting from multiple sources +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// Constant Buffer Variables +//-------------------------------------------------------------------------------------- +cbuffer Constants : register( b0 ) +{ + float4x4 mWorld; + float4x4 mView; + float4x4 mProjection; + float4 lightDir[ 2 ]; + float4 lightColor[ 2 ]; + float4 outputColor; +} + + +//-------------------------------------------------------------------------------------- +struct VS_INPUT +{ + float4 Pos : POSITION; + float3 Normal : NORMAL; +}; + +struct PS_INPUT +{ + float4 Pos : SV_POSITION; + float3 Normal : TEXCOORD0; +}; + + +//-------------------------------------------------------------------------------------- +// Name: TriangleVS +// Desc: Vertex shader +//-------------------------------------------------------------------------------------- +PS_INPUT TriangleVS( VS_INPUT input ) +{ + PS_INPUT output = ( PS_INPUT )0; + output.Pos = mul( input.Pos, mWorld ); + output.Pos = mul( output.Pos, mView ); + output.Pos = mul( output.Pos, mProjection ); + output.Normal = mul( input.Normal, ( ( float3x3 ) mWorld ) ); + + return output; +} + + +//-------------------------------------------------------------------------------------- +// Name: TrianglePS +// Desc: Pixel shader applying Lambertian lighting from two lights +//-------------------------------------------------------------------------------------- +float4 LambertPS( PS_INPUT input ) : SV_Target +{ + float4 finalColor = 0; + + //do NdotL lighting for 2 lights + for( int i=0; i< 2; i++ ) + { + finalColor += saturate( dot( ( float3 ) lightDir[ i ], input.Normal ) * lightColor[ i ] ); + } + finalColor.a = 1; + return finalColor; +} + + +//-------------------------------------------------------------------------------------- +// Name: TriangleSolidColorPS +// Desc: Pixel shader applying solid color +//-------------------------------------------------------------------------------------- +float4 SolidColorPS( PS_INPUT input ) : SV_Target +{ + return outputColor; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.sln b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.sln new file mode 100644 index 0000000000000000000000000000000000000000..9d111141db64b34fd621f17158e91959845838ea --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleLighting", "SimpleLighting.vcxproj", "{933DC6CA-057B-437E-9BC4-FE03F89DF3B6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Debug|Durango.ActiveCfg = Debug|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Debug|Durango.Build.0 = Debug|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Debug|Durango.Deploy.0 = Debug|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Profile|Durango.ActiveCfg = Profile|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Profile|Durango.Build.0 = Profile|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Profile|Durango.Deploy.0 = Profile|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Release|Durango.ActiveCfg = Release|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Release|Durango.Build.0 = Release|Durango + {933DC6CA-057B-437E-9BC4-FE03F89DF3B6}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.vcxproj b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..af6fed30832a4a581b0d088996a8ed93eb1466a7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.vcxproj @@ -0,0 +1,236 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleLighting + {933dc6ca-057b-437e-9bc4-fe03f89df3b6} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + Pixel + Pixel + Pixel + LambertPS + LambertPS + LambertPS + + + Pixel + Pixel + Pixel + SolidColorPS + SolidColorPS + SolidColorPS + + + Vertex + Vertex + Vertex + TriangleVS + TriangleVS + TriangleVS + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..fd1f1fb26bcbefad1010b03517e3b303f1c409e7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SimpleLighting.vcxproj.filters @@ -0,0 +1,82 @@ + + + + + 359962b4-83cd-4229-bb77-d522f1b4a6be + + + b1a332aa-5b16-4e64-bcc8-bd939339de13 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {f980487d-013a-47ef-88dc-b4411d80a1d4} + + + {a48f29ea-8acf-47d2-9f43-015bec552f90} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Shaders + + + Shaders + + + Shaders + + + + + Shaders + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/SolidColorPS.hlsl b/XDKSamples/IntroGraphics/SimpleLighting/SolidColorPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..76bc9bd2264e3ff6cef61c7e9bbcf9a329facc64 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/SolidColorPS.hlsl @@ -0,0 +1,2 @@ +// SolidColorPS.hlsl file to provide an MSBuild target for the SolidColorPS pixel-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/StepTimer.h b/XDKSamples/IntroGraphics/SimpleLighting/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting/Telemetry.h b/XDKSamples/IntroGraphics/SimpleLighting/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleLighting/TriangleVS.hlsl b/XDKSamples/IntroGraphics/SimpleLighting/TriangleVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..5e72fb9bea2c8c10aed26cfffe6ab7a654f93ce5 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/TriangleVS.hlsl @@ -0,0 +1,2 @@ +// TriangleVS.hlsl file to provide an MSBuild target for the TriangleVS vertex-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting/pch.cpp b/XDKSamples/IntroGraphics/SimpleLighting/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleLighting/pch.h b/XDKSamples/IntroGraphics/SimpleLighting/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..5f41518fa6b7cc4c2d9d5d988e6a917060ef29ca --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting/pch.h @@ -0,0 +1,64 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleLighting12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleLighting12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/LambertPS.hlsl b/XDKSamples/IntroGraphics/SimpleLighting12/LambertPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..0458f99b45ca7437238923bedec61a8ab83ad64e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/LambertPS.hlsl @@ -0,0 +1,2 @@ +// LambertPS.hlsl file to provide an MSBuild target for the LambertPS pixel-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Main.cpp b/XDKSamples/IntroGraphics/SimpleLighting12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18b295f0226a5f0f4ab4f2b72a703e1b47b0a0ff --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleLighting12.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleLighting12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..0a11f412dbc890406b5487f1b04f5f2e679f1169 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleLighting12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleLighting12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Readme.docx b/XDKSamples/IntroGraphics/SimpleLighting12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..89cb38b6c6f1a9627c6075fd66062f77d7dff2a6 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleLighting12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting.hlsli b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..14218d8337718e9efc1fa93942b758d300c0ddde --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting.hlsli @@ -0,0 +1,89 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting.hlsl +// +// Shader demonstrating Lambertian lighting from multiple sources +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#define rootSig "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT" \ + "| DENY_DOMAIN_SHADER_ROOT_ACCESS " \ + "| DENY_GEOMETRY_SHADER_ROOT_ACCESS " \ + "| DENY_HULL_SHADER_ROOT_ACCESS), " \ + "CBV(b0, space = 0)" + + +//-------------------------------------------------------------------------------------- +// Constant Buffer Variables +//-------------------------------------------------------------------------------------- +cbuffer Constants : register( b0 ) +{ + float4x4 mWorld; + float4x4 mView; + float4x4 mProjection; + float4 lightDir[ 2 ]; + float4 lightColor[ 2 ]; + float4 outputColor; +}; + + +//-------------------------------------------------------------------------------------- +struct VS_INPUT +{ + float4 Pos : POSITION; + float3 Normal : NORMAL; +}; + +struct PS_INPUT +{ + float4 Pos : SV_POSITION; + float3 Normal : TEXCOORD0; +}; + + +//-------------------------------------------------------------------------------------- +// Name: TriangleVS +// Desc: Vertex shader +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +PS_INPUT TriangleVS( VS_INPUT input ) +{ + PS_INPUT output = ( PS_INPUT )0; + output.Pos = mul( input.Pos, mWorld ); + output.Pos = mul( output.Pos, mView ); + output.Pos = mul( output.Pos, mProjection ); + output.Normal = mul( input.Normal, ( ( float3x3 ) mWorld ) ); + + return output; +} + + +//-------------------------------------------------------------------------------------- +// Name: TrianglePS +// Desc: Pixel shader applying Lambertian lighting from two lights +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +float4 LambertPS( PS_INPUT input ) : SV_Target +{ + float4 finalColor = 0; + + //do NdotL lighting for 2 lights + for( int i=0; i< 2; i++ ) + { + finalColor += saturate( dot( ( float3 ) lightDir[ i ], input.Normal ) * lightColor[ i ] ); + } + finalColor.a = 1; + return finalColor; +} + + +//-------------------------------------------------------------------------------------- +// Name: TriangleSolidColorPS +// Desc: Pixel shader applying solid color +//-------------------------------------------------------------------------------------- +[RootSignature(rootSig)] +float4 SolidColorPS( PS_INPUT input ) : SV_Target +{ + return outputColor; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.cpp b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56d94af79cc11f0215fb6f61a7551a40b1dfc850 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.cpp @@ -0,0 +1,536 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleLighting12.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + struct Vertex + { + XMFLOAT3 pos; + XMFLOAT3 normal; + }; +} + +Sample::Sample() + : m_frame(0) + , m_mappedConstantData(nullptr) + , m_constantDataGpuAddr(0) + , m_curRotationAngleRad(0.0f) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + // Update the rotation constant + m_curRotationAngleRad += elapsedTime / 3.f; + if (m_curRotationAngleRad >= XM_2PI) + { + m_curRotationAngleRad -= XM_2PI; + } + + // Rotate the cube around the origin + XMStoreFloat4x4(&m_worldMatrix, XMMatrixRotationY(m_curRotationAngleRad)); + + // Setup our lighting parameters + m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); + m_lightDirs[1] = XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f); + + m_lightColors[0] = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); + m_lightColors[1] = XMFLOAT4(0.5f, 0.0f, 0.0f, 1.0f); + + // Rotate the second light around the origin + XMMATRIX rotate = XMMatrixRotationY(-2.0f * m_curRotationAngleRad); + XMVECTOR lightDir = XMLoadFloat4(&m_lightDirs[1]); + lightDir = XMVector3Transform(lightDir, rotate); + XMStoreFloat4(&m_lightDirs[1], lightDir); + + // Handle controller input for exit + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Check to see if the GPU is keeping up + int frameIdx = m_deviceResources->GetCurrentFrameIndex(); + int numBackBuffers = m_deviceResources->GetBackBufferCount(); + uint64_t completedValue = m_fence->GetCompletedValue(); + if ((frameIdx > completedValue) // if frame index is reset to zero it may temporarily be smaller than the last GPU signal + && (frameIdx - completedValue > numBackBuffers)) + { + // GPU not caught up, wait for at least one available frame + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(frameIdx - numBackBuffers, m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Index into the available constant buffers based on the number + // of draw calls. We've allocated enough for a known number of + // draw calls per frame times the number of back buffers + unsigned int constantBufferIndex = c_numDrawCalls * (frameIdx % numBackBuffers); + + // Set the root signature and pipeline state for the command list + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(m_lambertPipelineState.Get()); + + // Set the per-frame constants + ConstantBuffer sceneParameters = {}; + + // Shaders compiled with default row-major matrices + sceneParameters.worldMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_worldMatrix)); + sceneParameters.viewMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_viewMatrix)); + sceneParameters.projectionMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_projectionMatrix)); + + sceneParameters.lightDir[0] = XMLoadFloat4(&m_lightDirs[0]); + sceneParameters.lightDir[1] = XMLoadFloat4(&m_lightDirs[1]); + sceneParameters.lightColor[0] = XMLoadFloat4(&m_lightColors[0]); + sceneParameters.lightColor[1] = XMLoadFloat4(&m_lightColors[1]); + sceneParameters.outputColor = XMLoadFloat4(&m_outputColor); + + // Set the constants for the first draw call + memcpy(&m_mappedConstantData[constantBufferIndex].constants, &sceneParameters, sizeof(ConstantBuffer)); + + // Bind the constants to the shader + auto baseGpuAddress = m_constantDataGpuAddr + sizeof(PaddedConstantBuffer) * constantBufferIndex; + commandList->SetGraphicsRootConstantBufferView(c_rootParameterCB, baseGpuAddress); + + // Set up the input assembler + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); + commandList->IASetIndexBuffer(&m_indexBufferView); + + // Draw the Lambert lit cube + commandList->DrawIndexedInstanced(36, 1, 0, 0, 0); + baseGpuAddress += sizeof(PaddedConstantBuffer); + ++constantBufferIndex; + + // Render each light + commandList->SetPipelineState(m_solidColorPipelineState.Get()); + + for (int m = 0; m < 2; ++m) + { + XMMATRIX lightMatrix = XMMatrixTranslationFromVector(5.0f * sceneParameters.lightDir[m]); + XMMATRIX lightScaleMatrix = XMMatrixScaling(0.2f, 0.2f, 0.2f); + lightMatrix = lightScaleMatrix * lightMatrix; + + // Update the world variable to reflect the current light + sceneParameters.worldMatrix = XMMatrixTranspose(lightMatrix); + sceneParameters.outputColor = sceneParameters.lightColor[m]; + + // Set the constants for the draw call + memcpy(&m_mappedConstantData[constantBufferIndex].constants, &sceneParameters, sizeof(ConstantBuffer)); + + // Bind the constants to the shader + commandList->SetGraphicsRootConstantBufferView(c_rootParameterCB, baseGpuAddress); + + commandList->DrawIndexedInstanced(36, 1, 0, 0, 0); + baseGpuAddress += sizeof(PaddedConstantBuffer); + ++constantBufferIndex; + } + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + + // GPU will signal an increasing value each frame + m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), frameIdx); + + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + // Use linear clear color for gamma-correct rendering. + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + // Create a root signature with one constant buffer view + { + CD3DX12_ROOT_PARAMETER rp = {}; + rp.InitAsConstantBufferView(c_rootParameterCB, 0); + + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + rootSignatureDesc.Init(1, &rp, 0, nullptr, + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT + | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS + | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS + | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS); + + ComPtr signature; + ComPtr error; + HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); + if (FAILED(hr)) + { + if (error) + { + OutputDebugStringA(reinterpret_cast(error->GetBufferPointer())); + } + throw DX::com_exception(hr); + } + + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create the constant buffer memory and map the CPU and GPU addresses + { + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + size_t cbSize = c_numDrawCalls * m_deviceResources->GetBackBufferCount() * sizeof(PaddedConstantBuffer); + + const D3D12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(cbSize); + DX::ThrowIfFailed(device->CreateCommittedResource( + &uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &constantBufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_perFrameConstants.ReleaseAndGetAddressOf()))); + + DX::ThrowIfFailed(m_perFrameConstants->Map(0, nullptr, reinterpret_cast< void** >(&m_mappedConstantData))); + + m_constantDataGpuAddr = m_perFrameConstants->GetGPUVirtualAddress(); + } + + // Load the shader blob for the vertex shader that will be shared by two pipeline state objects + { + auto triangleVSBlob = DX::ReadData(L"TriangleVS.cso"); + + // Input element descriptor also shared by two pipeline state objects + static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + // Create the Pipelline State Object for the Lambert pixel shader + { + auto lambertPSBlob = DX::ReadData(L"LambertPS.cso"); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { triangleVSBlob.data(), triangleVSBlob.size() }; + psoDesc.PS = { lambertPSBlob.data(), lambertPSBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_GRAPHICS_PPV_ARGS(m_lambertPipelineState.ReleaseAndGetAddressOf()))); + } + + // Create the Pipeline State Object for the solid color pixel shader + { + auto solidColorPSBlob = DX::ReadData(L"SolidColorPS.cso"); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { triangleVSBlob.data(), triangleVSBlob.size() }; + psoDesc.PS = { solidColorPSBlob.data(), solidColorPSBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_GRAPHICS_PPV_ARGS(m_solidColorPipelineState.ReleaseAndGetAddressOf()))); + } + } + + // Create the vertex buffer + { + static const Vertex vertices[] = + { + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + }; + + // Note: using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are very few verts to actually transfer. + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + const CD3DX12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(vertices)); + DX::ThrowIfFailed( + device->CreateCommittedResource(&uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_vertexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the data to the vertex buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_vertexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, vertices, sizeof(vertices)); + m_vertexBuffer->Unmap(0, nullptr); + + // Initialize the vertex buffer view. + m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); + m_vertexBufferView.StrideInBytes = sizeof(Vertex); + m_vertexBufferView.SizeInBytes = sizeof(vertices); + } + + // Create the index buffer + { + static const uint16_t indices[] = + { + 3,1,0, + 2,1,3, + + 6,4,5, + 7,4,6, + + 11,9,8, + 10,9,11, + + 14,12,13, + 15,12,14, + + 19,17,16, + 18,17,19, + + 22,20,21, + 23,20,22 + }; + + // See note above + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + const CD3DX12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(indices)); + DX::ThrowIfFailed( + device->CreateCommittedResource(&uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_indexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the data to the index buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_indexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, indices, sizeof(indices)); + m_indexBuffer->Unmap(0, nullptr); + + // Initialize the index buffer view. + m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); + m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; + m_indexBufferView.SizeInBytes = sizeof(indices); + } + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); + + // Create a fence for synchronizing between the CPU and the GPU + DX::ThrowIfFailed(device->CreateFence(m_deviceResources->GetCurrentFrameIndex(), D3D12_FENCE_FLAG_NONE, + IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + + // Start off the fence with the current frame index + uint64_t currentIdx = m_deviceResources->GetCurrentFrameIndex(); + m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), currentIdx); + + // Initialize the world matrix + XMStoreFloat4x4(&m_worldMatrix, XMMatrixIdentity()); + + // Initialize the view matrix + static const XMVECTORF32 c_eye = { 0.0f, 4.0f, -10.0f, 0.0f }; + static const XMVECTORF32 c_at = { 0.0f, 1.0f, 0.0f, 0.0f }; + static const XMVECTORF32 c_up = { 0.0f, 1.0f, 0.0f, 0.0 }; + XMStoreFloat4x4(&m_viewMatrix, XMMatrixLookAtLH(c_eye, c_at, c_up)); + + // Initialize the lighting parameters + m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); + m_lightDirs[1] = XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f); + + m_lightColors[0] = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); + m_lightColors[1] = XMFLOAT4(0.5f, 0.0f, 0.0f, 1.0f); + + // Initialize the scene output color + m_outputColor = XMFLOAT4(0, 0, 0, 0); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + // Initialize the projection matrix + auto size = m_deviceResources->GetOutputSize(); + XMMATRIX projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.01f, 100.0f); + + XMStoreFloat4x4(&m_projectionMatrix, projection); +} +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.h b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.h new file mode 100644 index 0000000000000000000000000000000000000000..63d149e907a083df0520eefca57c98ced55ba662 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.h @@ -0,0 +1,114 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + struct ConstantBuffer + { + DirectX::XMMATRIX worldMatrix; + DirectX::XMMATRIX viewMatrix; + DirectX::XMMATRIX projectionMatrix; + DirectX::XMVECTOR lightDir[2]; + DirectX::XMVECTOR lightColor[2]; + DirectX::XMVECTOR outputColor; + }; + + // We'll allocate space for several of these and they will need to be padded for alignment. + static_assert(sizeof(ConstantBuffer) == 272, "Checking the size here."); + + // D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT < 272 < 2 * D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT + // Create a union with the correct size and enough room for one ConstantBuffer + union PaddedConstantBuffer + { + ConstantBuffer constants; + uint8_t bytes[2 * D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT]; + }; + + // Check the exact size of the PaddedConstantBuffer to make sure it will align properly + static_assert(sizeof(PaddedConstantBuffer) == 2 * D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, "PaddedConstantBuffer is not aligned properly"); + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_lambertPipelineState; + Microsoft::WRL::ComPtr m_solidColorPipelineState; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_perFrameConstants; + PaddedConstantBuffer* m_mappedConstantData; + D3D12_GPU_VIRTUAL_ADDRESS m_constantDataGpuAddr; + D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView; + D3D12_INDEX_BUFFER_VIEW m_indexBufferView; + + // In this simple sample, we know that there are three draw calls + // and we will update the scene constants for each draw call. + static const unsigned int c_numDrawCalls = 3; + + // A synchronization fence and an event. These members will be used + // to synchronize the CPU with the GPU so that there will be no + // contention for the constant buffers. + Microsoft::WRL::ComPtr m_fence; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Index in the root parameter table + static const UINT c_rootParameterCB = 0; + + // Scene constants, updated per-frame + float m_curRotationAngleRad; + + // These computed values will be loaded into a ConstantBuffer + // during Render + DirectX::XMFLOAT4X4 m_worldMatrix; + DirectX::XMFLOAT4X4 m_viewMatrix; + DirectX::XMFLOAT4X4 m_projectionMatrix; + DirectX::XMFLOAT4 m_lightDirs[2]; + DirectX::XMFLOAT4 m_lightColors[2]; + DirectX::XMFLOAT4 m_outputColor; +}; diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.sln b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.sln new file mode 100644 index 0000000000000000000000000000000000000000..e19064b033547daf4f532124c60d0d1fd9aca093 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleLighting12", "SimpleLighting12.vcxproj", "{1B4F6C7B-E541-4333-B535-9A10BB898531}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Debug|Durango.ActiveCfg = Debug|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Debug|Durango.Build.0 = Debug|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Debug|Durango.Deploy.0 = Debug|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Profile|Durango.ActiveCfg = Profile|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Profile|Durango.Build.0 = Profile|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Profile|Durango.Deploy.0 = Profile|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Release|Durango.ActiveCfg = Release|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Release|Durango.Build.0 = Release|Durango + {1B4F6C7B-E541-4333-B535-9A10BB898531}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.vcxproj b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..7b04b4bb50f900a3c2bf681f642d5bfefe0f85e9 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.vcxproj @@ -0,0 +1,234 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleLighting12 + {1b4f6c7b-e541-4333-b535-9a10bb898531} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + Pixel + Pixel + Pixel + LambertPS + LambertPS + LambertPS + + + Pixel + Pixel + Pixel + SolidColorPS + SolidColorPS + SolidColorPS + + + Vertex + Vertex + Vertex + TriangleVS + TriangleVS + TriangleVS + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..cd666948c14460046f9c570abbae84b747997484 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SimpleLighting12.vcxproj.filters @@ -0,0 +1,82 @@ + + + + + 60e0865e-05a0-49ff-9e9c-13ad2a392dbc + + + 8ae2e8b7-1e0a-4fcf-baf1-8529762ab97d + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {bb9e0997-e3ab-4bdd-86de-bbb686933500} + + + {717c28bc-bf40-49f8-8bcd-2d8261e4b538} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + Common + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Shaders + + + + + + Shaders + + + Shaders + + + Shaders + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/SolidColorPS.hlsl b/XDKSamples/IntroGraphics/SimpleLighting12/SolidColorPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..76bc9bd2264e3ff6cef61c7e9bbcf9a329facc64 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/SolidColorPS.hlsl @@ -0,0 +1,2 @@ +// SolidColorPS.hlsl file to provide an MSBuild target for the SolidColorPS pixel-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleLighting12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleLighting12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/TriangleVS.hlsl b/XDKSamples/IntroGraphics/SimpleLighting12/TriangleVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..5e72fb9bea2c8c10aed26cfffe6ab7a654f93ce5 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/TriangleVS.hlsl @@ -0,0 +1,2 @@ +// TriangleVS.hlsl file to provide an MSBuild target for the TriangleVS vertex-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/pch.cpp b/XDKSamples/IntroGraphics/SimpleLighting12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleLighting12/pch.h b/XDKSamples/IntroGraphics/SimpleLighting12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..162dd9d1fd8fba0987af8b5d6a3638c2ea589365 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleLighting12/pch.h @@ -0,0 +1,63 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleMSAA/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleMSAA/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Main.cpp b/XDKSamples/IntroGraphics/SimpleMSAA/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5ab32d65dfd984924e38be736f7fb6d49045ad9 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleMSAA/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..bd8a64f8e313cdd9c1b9a4f7c9f10fbb84403c92 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleMSAA + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleMSAA + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Readme.docx b/XDKSamples/IntroGraphics/SimpleMSAA/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..1bd6b1a6a243ed6b2a3947b6a9cee51a0cd680b4 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7bf0abf044e75937122aff607e7e7d65eee97d12 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.cpp @@ -0,0 +1,372 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.cpp +// +// This sample demonstrates setting up a MSAA render target for DirectX 11 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +#define USE_FAST_SEMANTICS + +extern void ExitSample(); + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +namespace +{ + const DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; + + // Xbox One supports 2x, 4x, or 8x MSAA + const unsigned int c_sampleCount = 4; +} + +Sample::Sample() : + m_msaa(true), + m_frame(0) +{ + unsigned int flags = 0; + +#ifdef ENABLE_4K + flags |= DX::DeviceResources::c_Enable4K_UHD; +#endif + +#ifdef USE_FAST_SEMANTICS + flags |= DX::DeviceResources::c_FastSemantics; +#endif + + m_deviceResources = std::make_unique( + c_backBufferFormat, + c_depthBufferFormat, /* If we were only doing MSAA rendering, we could skip the non-MSAA depth/stencil buffer with DXGI_FORMAT_UNKNOWN */ + 2, + flags); + + // + // In Win32 'classic' DirectX 11, you can create the 'swapchain' backbuffer as a multisample buffer. Present took care of the + // resolve as part of the swapchain management. This approach is not recommended as doing it explictly gives you more control + // as well as the fact that this 'old-school' implicit resolve behavior is not supported for UWP or DirectX 12. + // +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float time = float(timer.GetTotalSeconds()); + + m_world = Matrix::CreateRotationZ(cosf(time / 4.f)); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_msaa = !m_msaa; + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Draw the scene. + m_model->Draw(context, *m_states, m_world, m_view, m_proj); + + PIXEndEvent(context); + + if (m_msaa) + { + // Resolve the MSAA render target. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Resolve"); + +#ifdef USE_FAST_SEMANTICS + context->DecompressResource( + m_msaaRenderTarget.Get(), 0, nullptr, + m_msaaRenderTarget.Get(), 0, nullptr, + c_backBufferFormat, D3D11X_DECOMPRESS_ALL); +#endif + + auto backBuffer = m_deviceResources->GetRenderTarget(); + context->ResolveSubresource(backBuffer, 0, m_msaaRenderTarget.Get(), 0, c_backBufferFormat); + + PIXEndEvent(context); + + // Set render target for UI which is typically rendered without MSAA. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + context->OMSetRenderTargets(1, &renderTarget, nullptr); + } + + // Draw UI. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Draw UI"); + + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + m_batch->Begin(); + + wchar_t str[32] = {}; + swprintf_s(str, L"Sample count: %u", m_msaa ? c_sampleCount : 1); + m_smallFont->DrawString(m_batch.get(), str, XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::White); + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + L"[A] Toggle MSAA [View] Exit", + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + Present(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + + if (m_msaa) + { + // + // Rather than operate on the swapchain render target, we set up to render the scene to our MSAA resources instead. + // + + context->ClearRenderTargetView(m_msaaRenderTargetView.Get(), ATG::ColorsLinear::Background); + context->ClearDepthStencilView(m_msaaDepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, m_msaaRenderTargetView.GetAddressOf(), m_msaaDepthStencilView.Get()); + } + else + { + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + } + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} + +// Presents the back buffer contents to the screen. +void Sample::Present() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + + if (m_msaa) + { + // + // Present our swapchain (skipping any 11.X Fast Semantic decompress since we already did it above). + // + + m_deviceResources->Present(0); + } + else + { + m_deviceResources->Present(); + } + + m_graphicsMemory->Commit(); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + m_batch = std::make_unique(context); + + m_states = std::make_unique(device); + + m_fxFactory = std::make_unique(device); + + m_model = Model::CreateFromSDKMESH(device, L"CityBlockConcrete.sdkmesh", *m_fxFactory); + + m_world = Matrix::Identity; +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto output = m_deviceResources->GetOutputSize(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(output.right - output.left, 1); + UINT backBufferHeight = std::max(output.bottom - output.top, 1); + + // Create an MSAA render target. + CD3D11_TEXTURE2D_DESC renderTargetDesc( + c_backBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // The render target view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_RENDER_TARGET, + D3D11_USAGE_DEFAULT, + 0, + c_sampleCount + ); + + auto device = m_deviceResources->GetD3DDevice(); + DX::ThrowIfFailed(device->CreateTexture2D( + &renderTargetDesc, + nullptr, + m_msaaRenderTarget.ReleaseAndGetAddressOf() + )); + + CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DMS, c_backBufferFormat); + + DX::ThrowIfFailed(device->CreateRenderTargetView( + m_msaaRenderTarget.Get(), + &renderTargetViewDesc, + m_msaaRenderTargetView.ReleaseAndGetAddressOf() + )); + + // Create an MSAA depth stencil view. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + c_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL, + D3D11_USAGE_DEFAULT, + 0, + c_sampleCount + ); + + ComPtr depthStencil; + DX::ThrowIfFailed(device->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + DX::ThrowIfFailed(device->CreateDepthStencilView( + depthStencil.Get(), + nullptr, + m_msaaDepthStencilView.ReleaseAndGetAddressOf() + )); + + // Load UI. + m_smallFont = std::make_unique(device, (output.bottom > 1080) ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, (output.bottom > 1080) ? L"XboxOneControllerLegend.spritefont" : L"XboxOneControllerLegendSmall.spritefont"); + + // Setup test scene. + m_view = Matrix::CreateLookAt(Vector3(0, -211.f, -23.f), Vector3(6.f, 0.f, -37.f), -Vector3::UnitZ); + + m_proj = Matrix::CreatePerspectiveFieldOfView(XM_PI / 4.f, + float(backBufferWidth) / float(backBufferHeight), 0.1f, 1000.f); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_batch->SetViewport(viewport); +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.h b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.h new file mode 100644 index 0000000000000000000000000000000000000000..2be7e8fea40fe673b2be47fc29609fc62d1cd8f5 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.h @@ -0,0 +1,78 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.h +// +// This sample demonstrates setting up a MSAA render target for DirectX 11 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + void Present(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // MSAA resources. + Microsoft::WRL::ComPtr m_msaaRenderTarget; + + Microsoft::WRL::ComPtr m_msaaRenderTargetView; + Microsoft::WRL::ComPtr m_msaaDepthStencilView; + + bool m_msaa; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_batch; + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + std::unique_ptr m_states; + std::unique_ptr m_model; + std::unique_ptr m_fxFactory; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_proj; +}; diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.sln b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.sln new file mode 100644 index 0000000000000000000000000000000000000000..0577f66849b355af6d65ac113c01dd6868c27631 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMSAA", "SimpleMSAA.vcxproj", "{30597E75-7F16-40C4-9B6B-C072301A30D3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Debug|Durango.ActiveCfg = Debug|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Debug|Durango.Build.0 = Debug|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Debug|Durango.Deploy.0 = Debug|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Profile|Durango.ActiveCfg = Profile|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Profile|Durango.Build.0 = Profile|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Profile|Durango.Deploy.0 = Profile|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Release|Durango.ActiveCfg = Release|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Release|Durango.Build.0 = Release|Durango + {30597E75-7F16-40C4-9B6B-C072301A30D3}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.vcxproj b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..eb7a57b6cc19df087ee8229be6fa0c046c09d0c1 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.vcxproj @@ -0,0 +1,236 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleMSAA + {30597e75-7f16-40c4-9b6b-c072301a30d3} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..eb60a31ab4cea1b45e7a12a6245e48f50e6e51df --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/SimpleMSAA.vcxproj.filters @@ -0,0 +1,86 @@ + + + + + d3236908-4337-4c1c-a694-602e766d4b57 + + + 4acedce2-d8cd-43ec-b6cf-b5cd5d90ec3e + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 5e952c9c-9a5b-4a6e-842e-174a9e692d67 + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/StepTimer.h b/XDKSamples/IntroGraphics/SimpleMSAA/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/Telemetry.h b/XDKSamples/IntroGraphics/SimpleMSAA/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/pch.cpp b/XDKSamples/IntroGraphics/SimpleMSAA/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleMSAA/pch.h b/XDKSamples/IntroGraphics/SimpleMSAA/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..baa926a43a3af337d05894699d768fb38097862e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA/pch.h @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "CommonStates.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Model.h" +#include "SpriteBatch.h" +#include "SimpleMath.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleMSAA12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleMSAA12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Main.cpp b/XDKSamples/IntroGraphics/SimpleMSAA12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5ab32d65dfd984924e38be736f7fb6d49045ad9 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleMSAA12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..9dc3edf62ea2e46634837b3c3b72d3729a448bd3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleMSAA + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleMSAA + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Readme.docx b/XDKSamples/IntroGraphics/SimpleMSAA12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..06fb33db273d74515b6cddfd026aecfa9c7930c5 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleMSAA12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.cpp b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9596ebf3563773af95f7f6dbe65f8b1dd801497 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.cpp @@ -0,0 +1,503 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.cpp +// +// This sample demonstrates setting up a MSAA render target for DirectX 12 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMSAA.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +extern void ExitSample(); + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +namespace +{ + const DXGI_FORMAT c_backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_depthBufferFormat = DXGI_FORMAT_D32_FLOAT; + +#if _XDK_VER < 0x3F6803F3 /* XDK Edition 170600 */ + // This is a workaround for a bug in the validation layer when resolving sRGB formats. + const DXGI_FORMAT c_msaaFormat = DXGI_FORMAT_B8G8R8A8_TYPELESS; + const DXGI_FORMAT c_resolveFormat = DXGI_FORMAT_B8G8R8A8_UNORM; +#else + const DXGI_FORMAT c_msaaFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + const DXGI_FORMAT c_resolveFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; +#endif + + // Xbox One supports 2x, 4x, or 8x MSAA + const unsigned int c_sampleCount = 4; +} + +Sample::Sample() : + m_msaa(true), + m_frame(0) +{ + unsigned int flags = 0; + +#ifdef ENABLE_4K + flags |= DX::DeviceResources::c_Enable4K_UHD; +#endif + + m_deviceResources = std::make_unique( + c_backBufferFormat, + c_depthBufferFormat, /* If we were only doing MSAA rendering, we could skip the non-MSAA depth/stencil buffer with DXGI_FORMAT_UNKNOWN */ + 2, + flags); + + // + // In Win32 'classic' DirectX 11, you can create the 'swapchain' backbuffer as a multisample buffer. Present took care of the + // resolve as part of the swapchain management. This is not recommended as doing it explictly gives you more control + // as well as the fact that this 'old-school' implicit resolve behavior is not supported for UWP. + // +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float time = float(timer.GetTotalSeconds()); + + m_world = Matrix::CreateRotationZ(cosf(time / 4.f)); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_msaa = !m_msaa; + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(m_msaa ? D3D12_RESOURCE_STATE_RENDER_TARGET : D3D12_RESOURCE_STATE_PRESENT); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Draw the scene. + ID3D12DescriptorHeap* heaps[] = { m_modelResources->Heap(), m_states->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Must use PSOs with MSAA sample counts that match our render target. + if (m_msaa) + { + Model::UpdateEffectMatrices(m_modelMSAA, m_world, m_view, m_proj); + + m_model->Draw(commandList, m_modelMSAA.cbegin()); + } + else + { + Model::UpdateEffectMatrices(m_modelStandard, m_world, m_view, m_proj); + + m_model->Draw(commandList, m_modelStandard.cbegin()); + } + + PIXEndEvent(commandList); + + if (m_msaa) + { + // Resolve the MSAA render target. + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Resolve"); + + auto backBuffer = m_deviceResources->GetRenderTarget(); + + { + D3D12_RESOURCE_BARRIER barriers[2] = + { + CD3DX12_RESOURCE_BARRIER::Transition( + m_msaaRenderTarget.Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_RESOLVE_SOURCE), + CD3DX12_RESOURCE_BARRIER::Transition( + backBuffer, + D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_RESOLVE_DEST) + }; + + commandList->ResourceBarrier(2, barriers); + } + + commandList->ResolveSubresource(backBuffer, 0, m_msaaRenderTarget.Get(), 0, c_resolveFormat); + + PIXEndEvent(commandList); + + // Set render target for UI which is typically rendered without MSAA. + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + backBuffer, + D3D12_RESOURCE_STATE_RESOLVE_DEST, + D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + } + } + + // Unbind depth/stencil for UI. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr); + + // Draw UI. + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw UI"); + + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + heaps[0] = m_resourceDescriptors->Heap(); + commandList->SetDescriptorHeaps(1, heaps); + + m_batch->Begin(commandList); + + wchar_t str[32] = {}; + swprintf_s(str, L"Sample count: %u", m_msaa ? c_sampleCount : 1); + m_smallFont->DrawString(m_batch.get(), str, XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::White); + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + L"[A] Toggle MSAA [View] Exit", + XMFLOAT2(float(safe.left), + float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + + if (m_msaa) + { + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_msaaRenderTarget.Get(), + D3D12_RESOURCE_STATE_RESOLVE_SOURCE, + D3D12_RESOURCE_STATE_RENDER_TARGET); + commandList->ResourceBarrier(1, &barrier); + + // + // Rather than operate on the swapchain render target, we set up to render the scene to our MSAA resources instead. + // + + auto rtvDescriptor = m_msaaRTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + auto dsvDescriptor = m_msaaDSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + } + else + { + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + } + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + // Create descriptor heaps for MSAA render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = 1; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + DX::ThrowIfFailed(device->CreateDescriptorHeap(&rtvDescriptorHeapDesc, + IID_GRAPHICS_PPV_ARGS(m_msaaRTVDescriptorHeap.ReleaseAndGetAddressOf()))); + + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(device->CreateDescriptorHeap(&dsvDescriptorHeapDesc, + IID_GRAPHICS_PPV_ARGS(m_msaaDSVDescriptorHeap.ReleaseAndGetAddressOf()))); + + // Setup test scene. + m_resourceDescriptors = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); + + m_states = std::make_unique(device); + + m_model = Model::CreateFromSDKMESH(L"CityBlockConcrete.sdkmesh"); + + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); + + m_modelResources = m_model->LoadTextures(device, resourceUpload); + + m_fxFactory = std::make_unique(m_modelResources->Heap(), m_states->Heap()); + + { + RenderTargetState rtStateUI(c_backBufferFormat, DXGI_FORMAT_UNKNOWN); + SpriteBatchPipelineStateDescription pd(rtStateUI); + + m_batch = std::make_unique(device, resourceUpload, pd); + } + + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + + { + RenderTargetState rtState(c_backBufferFormat, c_depthBufferFormat); + rtState.sampleDesc.Count = c_sampleCount; + + EffectPipelineStateDescription pd( + nullptr, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + EffectPipelineStateDescription pdAlpha( + nullptr, + CommonStates::AlphaBlend, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + m_modelMSAA = m_model->CreateEffects(*m_fxFactory, pd, pdAlpha); + } + + { + RenderTargetState rtState(c_backBufferFormat, c_depthBufferFormat); + + EffectPipelineStateDescription pd( + nullptr, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + EffectPipelineStateDescription pdAlpha( + nullptr, + CommonStates::AlphaBlend, + CommonStates::DepthDefault, + CommonStates::CullClockwise, + rtState); + + m_modelStandard = m_model->CreateEffects(*m_fxFactory, pd, pdAlpha); + } +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto output = m_deviceResources->GetOutputSize(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(output.right - output.left, 1); + UINT backBufferHeight = std::max(output.bottom - output.top, 1); + + CD3DX12_HEAP_PROPERTIES heapProperties(D3D12_HEAP_TYPE_DEFAULT); + + // Create an MSAA render target. + D3D12_RESOURCE_DESC msaaRTDesc = CD3DX12_RESOURCE_DESC::Tex2D( + c_msaaFormat, + backBufferWidth, + backBufferHeight, + 1, // This render target view has only one texture. + 1, // Use a single mipmap level + c_sampleCount + ); + msaaRTDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + + D3D12_CLEAR_VALUE msaaOptimizedClearValue = {}; + msaaOptimizedClearValue.Format = c_backBufferFormat; + memcpy(msaaOptimizedClearValue.Color, ATG::ColorsLinear::Background, sizeof(float) * 4); + + auto device = m_deviceResources->GetD3DDevice(); + DX::ThrowIfFailed(device->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &msaaRTDesc, + D3D12_RESOURCE_STATE_RESOLVE_SOURCE, + &msaaOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_msaaRenderTarget.ReleaseAndGetAddressOf()) + )); + + m_msaaRenderTarget->SetName(L"MSAA Render Target"); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = c_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS; + + device->CreateRenderTargetView( + m_msaaRenderTarget.Get(), &rtvDesc, + m_msaaRTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + + // Create an MSAA depth stencil view. + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + c_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + c_sampleCount + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = c_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + DX::ThrowIfFailed(device->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_msaaDepthStencil.ReleaseAndGetAddressOf()) + )); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = c_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS; + + device->CreateDepthStencilView( + m_msaaDepthStencil.Get(), &dsvDesc, + m_msaaDSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + + // Load UI. + ResourceUploadBatch resourceUpload(device); + resourceUpload.Begin(); + + m_smallFont = std::make_unique(device, resourceUpload, + (output.bottom > 1080) ? L"SegoeUI_36.spritefont" : L"SegoeUI_18.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::UIFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::UIFont)); + + m_ctrlFont = std::make_unique(device, resourceUpload, + (output.bottom > 1080) ? L"XboxOneControllerLegend.spritefont" : L"XboxOneControllerLegendSmall.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::CtrlFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::CtrlFont)); + + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + uploadResourcesFinished.wait(); + + // Setup test scene. + m_view = Matrix::CreateLookAt(Vector3(0, -211.f, -23.f), Vector3(6.f, 0.f, -37.f), -Vector3::UnitZ); + + m_proj = Matrix::CreatePerspectiveFieldOfView(XM_PI / 4.f, + float(backBufferWidth) / float(backBufferHeight), 0.1f, 1000.f); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_batch->SetViewport(viewport); +} +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.h b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.h new file mode 100644 index 0000000000000000000000000000000000000000..19593660e0204858f6508f4cfa79414daa778390 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.h @@ -0,0 +1,93 @@ +//-------------------------------------------------------------------------------------- +// SimpleMSAA.h +// +// This sample demonstrates setting up a MSAA render target for DirectX 12 +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // MSAA resources. + Microsoft::WRL::ComPtr m_msaaRenderTarget; + Microsoft::WRL::ComPtr m_msaaDepthStencil; + + Microsoft::WRL::ComPtr m_msaaRTVDescriptorHeap; + Microsoft::WRL::ComPtr m_msaaDSVDescriptorHeap; + + bool m_msaa; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + std::unique_ptr m_batch; + + std::unique_ptr m_resourceDescriptors; + + enum Descriptors + { + UIFont, + CtrlFont, + Count + }; + + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + std::unique_ptr m_states; + std::unique_ptr m_model; + std::unique_ptr m_modelResources; + std::unique_ptr m_fxFactory; + + std::vector> m_modelMSAA; + std::vector> m_modelStandard; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_proj; +}; diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.sln b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.sln new file mode 100644 index 0000000000000000000000000000000000000000..9051df1a16d708adffdc8ee56a0065bac4fb5db6 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMSAA", "SimpleMSAA.vcxproj", "{FDBC2AE2-E362-4720-993C-90E2093E3895}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Debug|Durango.ActiveCfg = Debug|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Debug|Durango.Build.0 = Debug|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Debug|Durango.Deploy.0 = Debug|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Profile|Durango.ActiveCfg = Profile|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Profile|Durango.Build.0 = Profile|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Profile|Durango.Deploy.0 = Profile|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Release|Durango.ActiveCfg = Release|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Release|Durango.Build.0 = Release|Durango + {FDBC2AE2-E362-4720-993C-90E2093E3895}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.vcxproj b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..567d27dc52d94f9aad9adf9a1e75a7e0eb4806d1 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.vcxproj @@ -0,0 +1,236 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleMSAA + {fdbc2ae2-e362-4720-993c-90e2093e3895} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..9eed9d6c9cfeccbb0de891fc18a738bb06b3672c --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/SimpleMSAA.vcxproj.filters @@ -0,0 +1,86 @@ + + + + + b0409339-3ebe-4a52-96e8-05422eed5235 + + + 4b786aa9-94d9-40aa-8189-48c0b0104746 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + f666f780-8235-41d5-ad76-e747c5ad03a4 + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleMSAA12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleMSAA12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/pch.cpp b/XDKSamples/IntroGraphics/SimpleMSAA12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleMSAA12/pch.h b/XDKSamples/IntroGraphics/SimpleMSAA12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..4ed192cd31eb3a02f14a011a12725fbe6a47cbf2 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleMSAA12/pch.h @@ -0,0 +1,73 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "CommonStates.h" +#include "DescriptorHeap.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Model.h" +#include "RenderTargetState.h" +#include "ResourceUploadBatch.h" +#include "SpriteBatch.h" +#include "SimpleMath.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleTexture/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleTexture/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleTexture/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleTexture/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleTexture/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleTexture/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleTexture/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Main.cpp b/XDKSamples/IntroGraphics/SimpleTexture/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72912ad23cc40ca417300313bcb1724225577190 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTexture.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleTexture/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..9c4f8b77ef3b68b34c015ecfdbf6621065890763 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleTexture + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleTexture + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleTexture/PixelShader.hlsl b/XDKSamples/IntroGraphics/SimpleTexture/PixelShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..20cb8cd579c2dea86613c9b86125bb366547cd55 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/PixelShader.hlsl @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------------ +// PixelShader.hlsl +// +// Simple shader to render a textured quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Interpolants +{ + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +struct Pixel +{ + float4 color : SV_Target; +}; + +Texture2D txDiffuse : register(t0); +SamplerState samLinear : register(s0); + +Pixel main( Interpolants In ) +{ + Pixel Out; + Out.color = txDiffuse.Sample(samLinear, In.texcoord); + return Out; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Readme.docx b/XDKSamples/IntroGraphics/SimpleTexture/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..d4a1fd56b117ebb6b88d47de9dc306e8db3b881f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.cpp b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62b1e7164b647c91a6b401e561578495450f4098 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.cpp @@ -0,0 +1,336 @@ +//-------------------------------------------------------------------------------------- +// SimpleTexture.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTexture.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + struct Vertex + { + XMFLOAT4 position; + XMFLOAT2 texcoord; + }; + + std::vector LoadBGRAImage(const wchar_t* filename, uint32_t& width, uint32_t& height) + { + ComPtr wicFactory; + DX::ThrowIfFailed(CoCreateInstance(CLSID_WICImagingFactory2, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wicFactory))); + + ComPtr decoder; + DX::ThrowIfFailed(wicFactory->CreateDecoderFromFilename(filename, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf())); + + ComPtr frame; + DX::ThrowIfFailed(decoder->GetFrame(0, frame.GetAddressOf())); + + DX::ThrowIfFailed(frame->GetSize(&width, &height)); + + WICPixelFormatGUID pixelFormat; + DX::ThrowIfFailed(frame->GetPixelFormat(&pixelFormat)); + + uint32_t rowPitch = width * sizeof(uint32_t); + uint32_t imageSize = rowPitch * height; + + std::vector image; + image.resize(size_t(imageSize)); + + if (memcmp(&pixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)) == 0) + { + DX::ThrowIfFailed(frame->CopyPixels(0, rowPitch, imageSize, reinterpret_cast(image.data()))); + } + else + { + ComPtr formatConverter; + DX::ThrowIfFailed(wicFactory->CreateFormatConverter(formatConverter.GetAddressOf())); + + BOOL canConvert = FALSE; + DX::ThrowIfFailed(formatConverter->CanConvert(pixelFormat, GUID_WICPixelFormat32bppBGRA, &canConvert)); + if (!canConvert) + { + throw std::exception("CanConvert"); + } + + DX::ThrowIfFailed(formatConverter->Initialize(frame.Get(), GUID_WICPixelFormat32bppBGRA, + WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut)); + + DX::ThrowIfFailed(formatConverter->CopyPixels(0, rowPitch, imageSize, reinterpret_cast(image.data()))); + } + + return image; + } +} + +Sample::Sample() : + m_frame(0) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Set input assembler state. + context->IASetInputLayout(m_spInputLayout.Get()); + + UINT strides = sizeof(Vertex); + UINT offsets = 0; + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->IASetVertexBuffers(0, 1, m_spVertexBuffer.GetAddressOf(), &strides, &offsets); + + context->IASetIndexBuffer(m_spIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0); + + // Set shaders. + context->VSSetShader(m_spVertexShader.Get(), nullptr, 0); + context->GSSetShader(nullptr, nullptr, 0); + context->PSSetShader(m_spPixelShader.Get(), nullptr, 0); + + // Set texture and sampler. + auto sampler = m_spSampler.Get(); + context->PSSetSamplers(0, 1, &sampler); + + auto texture = m_spTexture.Get(); + context->PSSetShaderResources(0, 1, &texture); + + // Draw quad. + context->DrawIndexed(6, 0, 0); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + // Use linear clear color for gamma-correct rendering. + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + // Load and create shaders. + auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); + + DX::ThrowIfFailed( + device->CreateVertexShader(vertexShaderBlob.data(), vertexShaderBlob.size(), + nullptr, m_spVertexShader.ReleaseAndGetAddressOf())); + + auto pixelShaderBlob = DX::ReadData(L"PixelShader.cso"); + + DX::ThrowIfFailed( + device->CreatePixelShader(pixelShaderBlob.data(), pixelShaderBlob.size(), + nullptr, m_spPixelShader.ReleaseAndGetAddressOf())); + + // Create input layout. + static const D3D11_INPUT_ELEMENT_DESC s_inputElementDesc[2] = + { + { "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA , 0 }, + }; + + DX::ThrowIfFailed( + device->CreateInputLayout(s_inputElementDesc, _countof(s_inputElementDesc), + vertexShaderBlob.data(), vertexShaderBlob.size(), + m_spInputLayout.ReleaseAndGetAddressOf())); + + // Create vertex buffer. + static const Vertex s_vertexData[4] = + { + { { -0.5f, -0.5f, 0.5f, 1.0f },{ 0.f, 1.f } }, + { { 0.5f, -0.5f, 0.5f, 1.0f },{ 1.f, 1.f } }, + { { 0.5f, 0.5f, 0.5f, 1.0f },{ 1.f, 0.f } }, + { { -0.5f, 0.5f, 0.5f, 1.0f },{ 0.f, 0.f } }, + }; + + D3D11_SUBRESOURCE_DATA initialData = {}; + initialData.pSysMem = s_vertexData; + + D3D11_BUFFER_DESC bufferDesc = {}; + bufferDesc.ByteWidth = sizeof(s_vertexData); + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.StructureByteStride = sizeof(Vertex); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, &initialData, + m_spVertexBuffer.ReleaseAndGetAddressOf())); + + // Create index buffer. + static const uint16_t s_indexData[6] = + { + 3,1,0, + 2,1,3, + }; + + initialData.pSysMem = s_indexData; + + bufferDesc.ByteWidth = sizeof(s_indexData); + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.StructureByteStride = sizeof(uint16_t); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, &initialData, + m_spIndexBuffer.ReleaseAndGetAddressOf())); + + // Create sampler. + D3D11_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + DX::ThrowIfFailed( + device->CreateSamplerState(&samplerDesc, + m_spSampler.ReleaseAndGetAddressOf())); + + // Create texture. + D3D11_TEXTURE2D_DESC txtDesc = {}; + txtDesc.MipLevels = txtDesc.ArraySize = 1; + txtDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; // sunset.jpg is in sRGB colorspace + txtDesc.SampleDesc.Count = 1; + txtDesc.Usage = D3D11_USAGE_IMMUTABLE; + txtDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + auto image = LoadBGRAImage(L"sunset.jpg", txtDesc.Width, txtDesc.Height); + + initialData.pSysMem = image.data(); + initialData.SysMemPitch = txtDesc.Width * sizeof(uint32_t); + + ComPtr tex; + DX::ThrowIfFailed( + device->CreateTexture2D(&txtDesc, &initialData, + tex.GetAddressOf())); + + DX::ThrowIfFailed( + device->CreateShaderResourceView(tex.Get(), + nullptr, m_spTexture.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.h b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..e5df7f29adfc5391d78f5c96cbbd8ad5ecaa29a4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.h @@ -0,0 +1,63 @@ +//-------------------------------------------------------------------------------------- +// SimpleTexture.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Sample objects + Microsoft::WRL::ComPtr m_spInputLayout; + Microsoft::WRL::ComPtr m_spVertexBuffer; + Microsoft::WRL::ComPtr m_spIndexBuffer; + Microsoft::WRL::ComPtr m_spVertexShader; + Microsoft::WRL::ComPtr m_spPixelShader; + Microsoft::WRL::ComPtr m_spSampler; + Microsoft::WRL::ComPtr m_spTexture; +}; diff --git a/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.sln b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.sln new file mode 100644 index 0000000000000000000000000000000000000000..bb25998227c67e685ff99c6806b92deb83e9dfea --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexture", "SimpleTexture.vcxproj", "{A370A52F-DD86-4D93-8E3E-0EC8249A2A57}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Debug|Durango.ActiveCfg = Debug|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Debug|Durango.Build.0 = Debug|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Debug|Durango.Deploy.0 = Debug|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Profile|Durango.ActiveCfg = Profile|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Profile|Durango.Build.0 = Profile|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Profile|Durango.Deploy.0 = Profile|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Release|Durango.ActiveCfg = Release|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Release|Durango.Build.0 = Release|Durango + {A370A52F-DD86-4D93-8E3E-0EC8249A2A57}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.vcxproj b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..38ad14d7acd8f0f518d1352b071d7141dcf54d74 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.vcxproj @@ -0,0 +1,222 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleTexture + {a370a52f-dd86-4d93-8e3e-0ec8249a2a57} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..8da1cf777288dcc74cede71c97eee450bfc63e9a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/SimpleTexture.vcxproj.filters @@ -0,0 +1,76 @@ + + + + + d00012df-c700-46ab-8b10-851143f0bc1b + + + 3c944265-0e72-4df5-9193-37a345cb2fc9 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {ca23ddea-b65d-4808-b6bc-586fc8c5a5eb} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture/StepTimer.h b/XDKSamples/IntroGraphics/SimpleTexture/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture/Telemetry.h b/XDKSamples/IntroGraphics/SimpleTexture/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleTexture/VertexShader.hlsl b/XDKSamples/IntroGraphics/SimpleTexture/VertexShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..cf407ff34f96f4514d0dac310bcb49ce75429322 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/VertexShader.hlsl @@ -0,0 +1,25 @@ +//-------------------------------------------------------------------------------------- +// VertexShader.hlsl +// +// Simple vertex shader for rendering a textured quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Vertex +{ + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +struct Interpolants +{ + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +Interpolants main( Vertex In ) +{ + return In; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture/pch.cpp b/XDKSamples/IntroGraphics/SimpleTexture/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleTexture/pch.h b/XDKSamples/IntroGraphics/SimpleTexture/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..fea028aaa6cd7487ee09400f6ade8664a704314d --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture/pch.h @@ -0,0 +1,66 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleTexture12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleTexture12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Main.cpp b/XDKSamples/IntroGraphics/SimpleTexture12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..135eeaa002210d471c186bb7daf9c2e953eb72e6 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTexture12.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleTexture12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..0bcdd6150bdebc514a92f1e7fda4ee6bc49ba111 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleTexture12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleTexture12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/PixelShader.hlsl b/XDKSamples/IntroGraphics/SimpleTexture12/PixelShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..bd61552dd77ef01a14c046cbad9212b708b7a267 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/PixelShader.hlsl @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------------ +// PixelShader.hlsl +// +// Simple shader to render a textured quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Interpolants +{ + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +struct Pixel +{ + float4 color : SV_Target; +}; + +Texture2D txDiffuse : register(t0); +SamplerState samLinear : register(s0); + +#define MainRS \ + "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT" \ + " | DENY_DOMAIN_SHADER_ROOT_ACCESS" \ + " | DENY_GEOMETRY_SHADER_ROOT_ACCESS" \ + " | DENY_HULL_SHADER_ROOT_ACCESS)," \ + "DescriptorTable (SRV(t0), visibility=SHADER_VISIBILITY_PIXEL),"\ + "StaticSampler(s0, visibility=SHADER_VISIBILITY_PIXEL)" + +[RootSignature(MainRS)] +Pixel main( Interpolants In ) +{ + Pixel Out; + Out.color = txDiffuse.Sample(samLinear, In.texcoord); + return Out; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Readme.docx b/XDKSamples/IntroGraphics/SimpleTexture12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..853c0a288d70ef43a70738e3d20341b05e06e609 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTexture12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.cpp b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b34565e733a6b248eaa093c02fa44f9f7eb63b3 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.cpp @@ -0,0 +1,447 @@ +//-------------------------------------------------------------------------------------- +// SimpleTexture12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTexture12.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#pragma warning(disable : 4238) + +namespace +{ + struct Vertex + { + XMFLOAT4 position; + XMFLOAT2 texcoord; + }; + + std::vector LoadBGRAImage(const wchar_t* filename, uint32_t& width, uint32_t& height) + { + ComPtr wicFactory; + DX::ThrowIfFailed(CoCreateInstance(CLSID_WICImagingFactory2, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wicFactory))); + + ComPtr decoder; + DX::ThrowIfFailed(wicFactory->CreateDecoderFromFilename(filename, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf())); + + ComPtr frame; + DX::ThrowIfFailed(decoder->GetFrame(0, frame.GetAddressOf())); + + DX::ThrowIfFailed(frame->GetSize(&width, &height)); + + WICPixelFormatGUID pixelFormat; + DX::ThrowIfFailed(frame->GetPixelFormat(&pixelFormat)); + + uint32_t rowPitch = width * sizeof(uint32_t); + uint32_t imageSize = rowPitch * height; + + std::vector image; + image.resize(size_t(imageSize)); + + if (memcmp(&pixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)) == 0) + { + DX::ThrowIfFailed(frame->CopyPixels(0, rowPitch, imageSize, reinterpret_cast(image.data()))); + } + else + { + ComPtr formatConverter; + DX::ThrowIfFailed(wicFactory->CreateFormatConverter(formatConverter.GetAddressOf())); + + BOOL canConvert = FALSE; + DX::ThrowIfFailed(formatConverter->CanConvert(pixelFormat, GUID_WICPixelFormat32bppBGRA, &canConvert)); + if (!canConvert) + { + throw std::exception("CanConvert"); + } + + DX::ThrowIfFailed(formatConverter->Initialize(frame.Get(), GUID_WICPixelFormat32bppBGRA, + WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut)); + + DX::ThrowIfFailed(formatConverter->CopyPixels(0, rowPitch, imageSize, reinterpret_cast(image.data()))); + } + + return image; + } +} + +Sample::Sample() : + m_frame(0) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(m_pipelineState.Get()); + + auto heap = m_srvHeap.Get(); + commandList->SetDescriptorHeaps(1, &heap); + + commandList->SetGraphicsRootDescriptorTable(0, m_srvHeap->GetGPUDescriptorHandleForHeapStart()); + + // Set necessary state. + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); + commandList->IASetIndexBuffer(&m_indexBufferView); + + // Draw quad. + commandList->DrawIndexedInstanced(6, 1, 0, 0, 0); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + // Use linear clear color for gamma-correct rendering. + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + // Create descriptor heaps. + { + // Describe and create a shader resource view (SRV) heap for the texture. + D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; + srvHeapDesc.NumDescriptors = 1; + srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + DX::ThrowIfFailed( + device->CreateDescriptorHeap(&srvHeapDesc, IID_GRAPHICS_PPV_ARGS(m_srvHeap.ReleaseAndGetAddressOf()))); + } + + // Create a root signature with one sampler and one texture + { + CD3DX12_DESCRIPTOR_RANGE descRange = {}; + descRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + + CD3DX12_ROOT_PARAMETER rp = {}; + rp.InitAsDescriptorTable(1, &descRange, D3D12_SHADER_VISIBILITY_PIXEL); + + // Use a static sampler that matches the defaults + // https://msdn.microsoft.com/en-us/library/windows/desktop/dn913202(v=vs.85).aspx#static_sampler + D3D12_STATIC_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_ANISOTROPIC; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + samplerDesc.MaxAnisotropy = 16; + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + rootSignatureDesc.Init(1, &rp, 1, &samplerDesc, + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT + | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS + | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS + | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS); + + ComPtr signature; + ComPtr error; + HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); + if (FAILED(hr)) + { + if (error) + { + OutputDebugStringA(reinterpret_cast(error->GetBufferPointer())); + } + throw DX::com_exception(hr); + } + + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create the pipeline state, which includes loading shaders. + auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); + + auto pixelShaderBlob = DX::ReadData(L"PixelShader.cso"); + + static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[2] = + { + { "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; + psoDesc.PS = { pixelShaderBlob.data(), pixelShaderBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_GRAPHICS_PPV_ARGS(m_pipelineState.ReleaseAndGetAddressOf()))); + + // Create vertex buffer. + { + static const Vertex s_vertexData[4] = + { + { { -0.5f, -0.5f, 0.5f, 1.0f },{ 0.f, 1.f } }, + { { 0.5f, -0.5f, 0.5f, 1.0f },{ 1.f, 1.f } }, + { { 0.5f, 0.5f, 0.5f, 1.0f },{ 1.f, 0.f } }, + { { -0.5f, 0.5f, 0.5f, 1.0f },{ 0.f, 0.f } }, + }; + + // Note: using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are very few verts to actually transfer. + DX::ThrowIfFailed( + device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_vertexData)), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_vertexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the quad data to the vertex buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_vertexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, s_vertexData, sizeof(s_vertexData)); + m_vertexBuffer->Unmap(0, nullptr); + + // Initialize the vertex buffer view. + m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); + m_vertexBufferView.StrideInBytes = sizeof(Vertex); + m_vertexBufferView.SizeInBytes = sizeof(s_vertexData); + } + + // Create index buffer. + { + static const uint16_t s_indexData[6] = + { + 3,1,0, + 2,1,3, + }; + + // See note above + DX::ThrowIfFailed( + device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_indexData)), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_indexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the data to the index buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_indexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, s_indexData, sizeof(s_indexData)); + m_indexBuffer->Unmap(0, nullptr); + + // Initialize the index buffer view. + m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); + m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; + m_indexBufferView.SizeInBytes = sizeof(s_indexData); + } + + // Create texture. + auto commandList = m_deviceResources->GetCommandList(); + commandList->Reset(m_deviceResources->GetCommandAllocator(), nullptr); + + ComPtr textureUploadHeap; + { + D3D12_RESOURCE_DESC txtDesc = {}; + txtDesc.MipLevels = txtDesc.DepthOrArraySize = 1; + txtDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; // sunset.jpg is in sRGB colorspace + txtDesc.SampleDesc.Count = 1; + txtDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + UINT width, height; + auto image = LoadBGRAImage(L"sunset.jpg", width, height); + txtDesc.Width = width; + txtDesc.Height = height; + + DX::ThrowIfFailed( + device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &txtDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_texture.ReleaseAndGetAddressOf()))); + + const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_texture.Get(), 0, 1); + + // Create the GPU upload buffer. + DX::ThrowIfFailed( + device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(textureUploadHeap.GetAddressOf()))); + + D3D12_SUBRESOURCE_DATA textureData = {}; + textureData.pData = image.data(); + textureData.RowPitch = static_cast(txtDesc.Width * sizeof(uint32_t)); + textureData.SlicePitch = image.size(); + + UpdateSubresources(commandList, m_texture.Get(), textureUploadHeap.Get(), 0, 0, 1, &textureData); + commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + + // Describe and create a SRV for the texture. + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = txtDesc.Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + device->CreateShaderResourceView(m_texture.Get(), &srvDesc, m_srvHeap->GetCPUDescriptorHandleForHeapStart()); + } + + DX::ThrowIfFailed(commandList->Close()); + m_deviceResources->GetCommandQueue()->ExecuteCommandLists(1, CommandListCast(&commandList)); + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.h b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.h new file mode 100644 index 0000000000000000000000000000000000000000..c8be815d4c01abd05702e73333372f4c215fa5d7 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.h @@ -0,0 +1,64 @@ +//-------------------------------------------------------------------------------------- +// SimpleTexture12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Direct3D 12 objects + Microsoft::WRL::ComPtr m_srvHeap; + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_pipelineState; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_texture; + D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView; + D3D12_INDEX_BUFFER_VIEW m_indexBufferView; +}; diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.sln b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.sln new file mode 100644 index 0000000000000000000000000000000000000000..bceb06729ff39bcc8a5413266b27b7176e4bf6e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexture12", "SimpleTexture12.vcxproj", "{406C44CA-FAEE-41C9-8C11-2FBDD50479E9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Debug|Durango.ActiveCfg = Debug|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Debug|Durango.Build.0 = Debug|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Debug|Durango.Deploy.0 = Debug|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Profile|Durango.ActiveCfg = Profile|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Profile|Durango.Build.0 = Profile|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Profile|Durango.Deploy.0 = Profile|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Release|Durango.ActiveCfg = Release|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Release|Durango.Build.0 = Release|Durango + {406C44CA-FAEE-41C9-8C11-2FBDD50479E9}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.vcxproj b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..0129ea6f00b942138ee851f13ed378abfbfa4242 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.vcxproj @@ -0,0 +1,222 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleTexture12 + {406c44ca-faee-41c9-8c11-2fbdd50479e9} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..5de7433114f2bf287aaec23ed798b9bf721ffc7c --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/SimpleTexture12.vcxproj.filters @@ -0,0 +1,76 @@ + + + + + b4a07fa5-de65-4b39-8efc-b750c9b95b9f + + + 0428499d-301b-43d4-8562-07978df8067d + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {bc098ff6-7719-47d9-8b9b-614d95ca2446} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleTexture12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleTexture12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/VertexShader.hlsl b/XDKSamples/IntroGraphics/SimpleTexture12/VertexShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..ffd57acd25ee592b0773074eca0e64d33a605c22 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/VertexShader.hlsl @@ -0,0 +1,34 @@ +//-------------------------------------------------------------------------------------- +// VertexShader.hlsl +// +// Simple vertex shader for rendering a textured quad +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Vertex +{ + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +struct Interpolants +{ + float4 position : SV_Position; + float2 texcoord : TEXCOORD0; +}; + +#define MainRS \ + "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT" \ + " | DENY_DOMAIN_SHADER_ROOT_ACCESS" \ + " | DENY_GEOMETRY_SHADER_ROOT_ACCESS" \ + " | DENY_HULL_SHADER_ROOT_ACCESS)," \ + "DescriptorTable (SRV(t0), visibility=SHADER_VISIBILITY_PIXEL),"\ + "StaticSampler(s0, visibility=SHADER_VISIBILITY_PIXEL)" + +[RootSignature(MainRS)] +Interpolants main( Vertex In ) +{ + return In; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/pch.cpp b/XDKSamples/IntroGraphics/SimpleTexture12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleTexture12/pch.h b/XDKSamples/IntroGraphics/SimpleTexture12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..5239123050cc5ceb106d70caf3595401d30faffe --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTexture12/pch.h @@ -0,0 +1,65 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleTriangle/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ca99545f78db66a34ee800ff3cd84cd17ea44aa --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/DeviceResources.cpp @@ -0,0 +1,249 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleTriangle/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..91df6da6619ba0d5d4d39afb0fc366ecc7be721f --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/DeviceResources.h @@ -0,0 +1,71 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Main.cpp b/XDKSamples/IntroGraphics/SimpleTriangle/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d0a20ab6cf83edcab338120683cfb90612a697e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTriangle.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleTriangle/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..070eba571136581d5d773cd79bd6081a164b6633 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleTriangle + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleTriangle + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/PixelShader.hlsl b/XDKSamples/IntroGraphics/SimpleTriangle/PixelShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..a08d078469bea3bf8c93650afd3f59933878aaba --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/PixelShader.hlsl @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------------ +// PixelShader.hlsl +// +// Simple shader to render a triangle +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Interpolants +{ + float4 position : SV_Position; + float4 color : COLOR0; +}; + +struct Pixel +{ + float4 color : SV_Target; +}; + +Pixel main( Interpolants In ) +{ + Pixel Out; + Out.color = In.color; + return Out; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Readme.docx b/XDKSamples/IntroGraphics/SimpleTriangle/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..84eda00277a60e0f99e0f9d8076d1cdda6bc3b0e Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9c024869d9af9a7db2540a57a7a90e8c1e6861d --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.cpp @@ -0,0 +1,227 @@ +//-------------------------------------------------------------------------------------- +// SimpleTriangle.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTriangle.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + struct Vertex + { + XMFLOAT4 position; + XMFLOAT4 color; + }; +} + +Sample::Sample() : + m_frame(0) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Set input assembler state + context->IASetInputLayout(m_spInputLayout.Get()); + + UINT strides = sizeof(Vertex); + UINT offsets = 0; + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->IASetVertexBuffers(0, 1, m_spVertexBuffer.GetAddressOf(), &strides, &offsets); + + // Set shaders + context->VSSetShader(m_spVertexShader.Get(), nullptr, 0); + context->GSSetShader(nullptr, nullptr, 0); + context->PSSetShader(m_spPixelShader.Get(), nullptr, 0); + + // Draw triangle + context->Draw(3, 0); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + // Use linear clear color for gamma-correct rendering. + context->ClearRenderTargetView(renderTarget, ATG::ColorsLinear::Background); + + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + // Load and create shaders + auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); + + DX::ThrowIfFailed( + device->CreateVertexShader(vertexShaderBlob.data(), vertexShaderBlob.size(), + nullptr, m_spVertexShader.ReleaseAndGetAddressOf())); + + auto pixelShaderBlob = DX::ReadData(L"PixelShader.cso"); + + DX::ThrowIfFailed( + device->CreatePixelShader(pixelShaderBlob.data(), pixelShaderBlob.size(), + nullptr, m_spPixelShader.ReleaseAndGetAddressOf())); + + // Create input layout + static const D3D11_INPUT_ELEMENT_DESC s_inputElementDesc[2] = + { + { "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA , 0 }, + }; + + DX::ThrowIfFailed( + device->CreateInputLayout(s_inputElementDesc, _countof(s_inputElementDesc), + vertexShaderBlob.data(), vertexShaderBlob.size(), + m_spInputLayout.ReleaseAndGetAddressOf())); + + // Create vertex buffer + static const Vertex s_vertexData[3] = + { + { { 0.0f, 0.5f, 0.5f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f } }, // Top / Red + { { 0.5f, -0.5f, 0.5f, 1.0f },{ 0.0f, 1.0f, 0.0f, 1.0f } }, // Right / Green + { { -0.5f, -0.5f, 0.5f, 1.0f },{ 0.0f, 0.0f, 1.0f, 1.0f } } // Left / Blue + }; + + D3D11_SUBRESOURCE_DATA initialData = { 0 }; + initialData.pSysMem = s_vertexData; + + D3D11_BUFFER_DESC bufferDesc = { 0 }; + bufferDesc.ByteWidth = sizeof(s_vertexData); + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.StructureByteStride = sizeof(Vertex); + + DX::ThrowIfFailed( + device->CreateBuffer(&bufferDesc, &initialData, + m_spVertexBuffer.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion + diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.h b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.h new file mode 100644 index 0000000000000000000000000000000000000000..ce7ace9a2b76256d10395b3c6fc0f654ad6c8c8b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.h @@ -0,0 +1,60 @@ +//-------------------------------------------------------------------------------------- +// SimpleTriangle.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Sample objects + Microsoft::WRL::ComPtr m_spInputLayout; + Microsoft::WRL::ComPtr m_spVertexBuffer; + Microsoft::WRL::ComPtr m_spVertexShader; + Microsoft::WRL::ComPtr m_spPixelShader; +}; diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.sln b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.sln new file mode 100644 index 0000000000000000000000000000000000000000..9935dbb899c70fca2f8e3e7226ec97a081720979 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTriangle", "SimpleTriangle.vcxproj", "{D41EF946-F0C8-4779-8BFA-61CA1567CFB5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Debug|Durango.ActiveCfg = Debug|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Debug|Durango.Build.0 = Debug|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Debug|Durango.Deploy.0 = Debug|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Profile|Durango.ActiveCfg = Profile|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Profile|Durango.Build.0 = Profile|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Profile|Durango.Deploy.0 = Profile|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Release|Durango.ActiveCfg = Release|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Release|Durango.Build.0 = Release|Durango + {D41EF946-F0C8-4779-8BFA-61CA1567CFB5}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.vcxproj b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..31538f090c120353b4a4136eecb282c68f7ed5b1 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.vcxproj @@ -0,0 +1,221 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleTriangle + {d41ef946-f0c8-4779-8bfa-61ca1567cfb5} + en-US + Win32Proj + title + + v140 + 11.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..c7a66df9800c594c13b5d00f21dcb5e6e927cc8c --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/SimpleTriangle.vcxproj.filters @@ -0,0 +1,73 @@ + + + + + 1f1640e2-96d7-4291-9124-615ee19c80f7 + + + 2daf3647-ebd4-4e22-9400-5b702469163f + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {45b53369-c2b4-4178-94f0-431ea800a545} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/StepTimer.h b/XDKSamples/IntroGraphics/SimpleTriangle/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/Telemetry.h b/XDKSamples/IntroGraphics/SimpleTriangle/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/VertexShader.hlsl b/XDKSamples/IntroGraphics/SimpleTriangle/VertexShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..677e879276a8261641b211f57758505383bfcd70 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/VertexShader.hlsl @@ -0,0 +1,25 @@ +//-------------------------------------------------------------------------------------- +// VertexShader.hlsl +// +// Simple vertex shader for rendering a triangle +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Vertex +{ + float4 position : SV_Position; + float4 color : COLOR0; +}; + +struct Interpolants +{ + float4 position : SV_Position; + float4 color : COLOR0; +}; + +Interpolants main( Vertex In ) +{ + return In; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/pch.cpp b/XDKSamples/IntroGraphics/SimpleTriangle/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleTriangle/pch.h b/XDKSamples/IntroGraphics/SimpleTriangle/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..470d0cd5063f2c23f85f0103290e20ba8a90ec14 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle/pch.h @@ -0,0 +1,66 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/Logo.png b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca6c2e9266d670339b481607b396cd35493fd7f Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/Logo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/SmallLogo.png b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..40dba78d40cedd7faa5390ebf93bc41f9d50f6fc Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/SmallLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/SplashScreen.png b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4d8d337963b8ba55bf525ebadb02ee2c848da8 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/SplashScreen.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/StoreLogo.png b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/StoreLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/WideLogo.png b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b175641ac1b73d8747a67f69468095a704706107 Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle12/Assets/WideLogo.png differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/DeviceResources.cpp b/XDKSamples/IntroGraphics/SimpleTriangle12/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825a246e786ccdcfb90ccb63700d1f6c9b529e4 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/DeviceResources.cpp @@ -0,0 +1,379 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_12_0), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } +} + +// Destructor for DeviceResources. +DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + // Create the DX12 API device object. + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; + +#if defined(_DEBUG) + // Enable the debug layer. + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED; +#endif + + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + + ThrowIfFailed(D3D12XboxCreateDevice( + nullptr, + ¶ms, + IID_GRAPHICS_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_GRAPHICS_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_GRAPHICS_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfigurationX(&hwConfig); + if (hwConfig.HardwareVersion >= D3D12XBOX_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // First, retrieve the underlying DXGI device from the D3D device. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + // Identify the physical adapter (GPU or card) this device is running on. + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + // And obtain the factory object that created it. + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a swap chain for the window. + ComPtr swapChain; + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), // Xbox One uses device here, not the command queue! + m_window, + &swapChainDesc, + nullptr, + m_swapChain.ReleaseAndGetAddressOf() + )); + } + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + ThrowIfFailed(m_swapChain->GetBuffer(n, IID_GRAPHICS_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = 0; + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_GRAPHICS_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// Prepare the command list and render target for rendering. +void DeviceResources::Prepare(D3D12_RESOURCE_STATES beforeState) +{ + // Reset command list and allocator. + ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + if (beforeState != D3D12_RESOURCE_STATE_RENDER_TARGET) + { + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(D3D12_RESOURCE_STATES beforeState) +{ + if (beforeState != D3D12_RESOURCE_STATE_PRESENT) + { + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), beforeState, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + } + + // Send the command list off to the GPU for processing. + ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + MoveToNextFrame(); +} + +// Wait for pending GPU work to complete. +void DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount; + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/DeviceResources.h b/XDKSamples/IntroGraphics/SimpleTriangle12/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6cf0179f107d5b01e505c4b6d85bb58b1b0c26 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/DeviceResources.h @@ -0,0 +1,100 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_Enable4K_UHD = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT); + void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Main.cpp b/XDKSamples/IntroGraphics/SimpleTriangle12/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1f4d92e1d4d0eef4abc7b335e03b3a9fd10f84e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTriangle12.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Package.appxmanifest b/XDKSamples/IntroGraphics/SimpleTriangle12/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..d35d17206a9ac6e218f0a5f43bdc145d5ea84e8e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleTriangle12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleTriangle12 + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/PixelShader.hlsl b/XDKSamples/IntroGraphics/SimpleTriangle12/PixelShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..367a5d8556f3b54de5a12a4a226dfc91b2c4080b --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/PixelShader.hlsl @@ -0,0 +1,27 @@ +//-------------------------------------------------------------------------------------- +// PixelShader.hlsl +// +// Simple shader to render a triangle +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Interpolants +{ + float4 position : SV_Position; + float4 color : COLOR0; +}; + +struct Pixel +{ + float4 color : SV_TARGET0; +}; + +[RootSignature("RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)")] +Pixel main( Interpolants In ) +{ + Pixel Out; + Out.color = In.color; + return Out; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Readme.docx b/XDKSamples/IntroGraphics/SimpleTriangle12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..161eb4ec0ffd6843fdd9627a9df29aeeffd6f28b Binary files /dev/null and b/XDKSamples/IntroGraphics/SimpleTriangle12/Readme.docx differ diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.cpp b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.cpp new file mode 100644 index 0000000000000000000000000000000000000000..593a1e9d3bfad9e29a6997c6947e07b36f9f9e85 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.cpp @@ -0,0 +1,262 @@ +//-------------------------------------------------------------------------------------- +// SimpleTriangle12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleTriangle12.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#pragma warning( disable : 4238 ) + +namespace +{ + struct Vertex + { + XMFLOAT4 position; + XMFLOAT4 color; + }; +} + +Sample::Sample() : + m_frame(0) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT, 2, + DX::DeviceResources::c_Enable4K_UHD); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(m_pipelineState.Get()); + + // Set necessary state. + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); + + // Draw triangle. + commandList->DrawInstanced(3, 1, 0, 0); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + + // Use linear clear color for gamma-correct rendering. + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); + +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->SuspendX(0); +} + +void Sample::OnResuming() +{ + auto queue = m_deviceResources->GetCommandQueue(); + queue->ResumeX(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + // Create an empty root signature. + { + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; + rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); + + ComPtr signature; + ComPtr error; + DX::ThrowIfFailed( + D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create the pipeline state, which includes loading shaders. + auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); + + auto pixelShaderBlob = DX::ReadData(L"PixelShader.cso"); + + static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[2] = + { + { "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 }, + }; + + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = { vertexShaderBlob.data(), vertexShaderBlob.size() }; + psoDesc.PS = { pixelShaderBlob.data(), pixelShaderBlob.size() }; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_GRAPHICS_PPV_ARGS(m_pipelineState.ReleaseAndGetAddressOf()))); + + // Create vertex buffer. + { + static const Vertex s_vertexData[3] = + { + { { 0.0f, 0.5f, 0.5f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f } }, // Top / Red + { { 0.5f, -0.5f, 0.5f, 1.0f },{ 0.0f, 1.0f, 0.0f, 1.0f } }, // Right / Green + { { -0.5f, -0.5f, 0.5f, 1.0f },{ 0.0f, 0.0f, 1.0f, 1.0f } } // Left / Blue + }; + + // Note: using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are very few verts to actually transfer. + DX::ThrowIfFailed( + device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_vertexData)), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(m_vertexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the triangle data to the vertex buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_vertexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, s_vertexData, sizeof(s_vertexData)); + m_vertexBuffer->Unmap(0, nullptr); + + // Initialize the vertex buffer view. + m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); + m_vertexBufferView.StrideInBytes = sizeof(Vertex); + m_vertexBufferView.SizeInBytes = sizeof(s_vertexData); + } + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.h b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.h new file mode 100644 index 0000000000000000000000000000000000000000..f9db00c923c8401331ed9a666765132af837bd33 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.h @@ -0,0 +1,60 @@ +//-------------------------------------------------------------------------------------- +// SimpleTriangle12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic Sample loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Direct3D 12 objects + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_pipelineState; + Microsoft::WRL::ComPtr m_vertexBuffer; + D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView; +}; diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.sln b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.sln new file mode 100644 index 0000000000000000000000000000000000000000..3dbac88d235d83978215eb85d92b09b34bc07b11 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTriangle12", "SimpleTriangle12.vcxproj", "{7BB4A226-108E-4D0A-93AE-EFD5129DF566}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_XboxOneXDK_2015.vcxproj", "{0EE6C863-556C-4815-8BFF-A5A0B25A948F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Debug|Durango.ActiveCfg = Debug|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Debug|Durango.Build.0 = Debug|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Debug|Durango.Deploy.0 = Debug|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Profile|Durango.ActiveCfg = Profile|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Profile|Durango.Build.0 = Profile|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Profile|Durango.Deploy.0 = Profile|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Release|Durango.ActiveCfg = Release|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Release|Durango.Build.0 = Release|Durango + {7BB4A226-108E-4D0A-93AE-EFD5129DF566}.Release|Durango.Deploy.0 = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.ActiveCfg = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Debug|Durango.Build.0 = Debug|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.ActiveCfg = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Profile|Durango.Build.0 = Profile|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.ActiveCfg = Release|Durango + {0EE6C863-556C-4815-8BFF-A5A0B25A948F}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.vcxproj b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..3331240209a7830e6790e21676825b08426e3e7c --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.vcxproj @@ -0,0 +1,227 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleTriangle12 + {7bb4a226-108e-4d0a-93ae-efd5129df566} + en-US + Win32Proj + title + + v140 + 11.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d12_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.1 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d12_x.lib;combase.lib;kernelx.lib;toolhelpx.lib;uuid.lib;etwplus.lib; + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + true + true + true + Pixel + Pixel + Pixel + + + true + true + true + Vertex + Vertex + Vertex + + + + + + + + {0ee6c863-556c-4815-8bff-a5a0b25a948f} + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.vcxproj.filters b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..9fd66339fa05b3a0f59852c623d87a587d8869ce --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/SimpleTriangle12.vcxproj.filters @@ -0,0 +1,73 @@ + + + + + bf052c57-af37-40d7-af06-8c9b50152490 + + + 11f46420-4945-452b-8fa9-84bd4f4634d2 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {b6eae013-804e-4952-bedf-3d87a77b3e5c} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/StepTimer.h b/XDKSamples/IntroGraphics/SimpleTriangle12/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/Telemetry.h b/XDKSamples/IntroGraphics/SimpleTriangle12/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/VertexShader.hlsl b/XDKSamples/IntroGraphics/SimpleTriangle12/VertexShader.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..0bae889d768bba7951c8adf0bcba58f706a0dd50 --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/VertexShader.hlsl @@ -0,0 +1,26 @@ +//-------------------------------------------------------------------------------------- +// VertexShader.hlsl +// +// Simple vertex shader for rendering a triangle +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +struct Vertex +{ + float4 position : SV_Position; + float4 color : COLOR0; +}; + +struct Interpolants +{ + float4 position : SV_Position; + float4 color : COLOR0; +}; + +[RootSignature("RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)")] +Interpolants main( Vertex In ) +{ + return In; +} \ No newline at end of file diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/pch.cpp b/XDKSamples/IntroGraphics/SimpleTriangle12/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/IntroGraphics/SimpleTriangle12/pch.h b/XDKSamples/IntroGraphics/SimpleTriangle12/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..82f0e6e053144891fbedef03c63e09a9c8cfb45e --- /dev/null +++ b/XDKSamples/IntroGraphics/SimpleTriangle12/pch.h @@ -0,0 +1,65 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/AsynchronousIO/AlertableOverlapped.cpp b/XDKSamples/System/AsynchronousIO/AlertableOverlapped.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6a3d6a67f0b74c99c34b8b840d41b79c5e88ca7 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/AlertableOverlapped.cpp @@ -0,0 +1,102 @@ +//-------------------------------------------------------------------------------------- +// AlertableOverlapped.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "OverlappedSample.h" + +//************************************ +// Method: FileIOCompletionRoutine +// Parameter: DWORD dwErrorCode +// Parameter: DWORD dwNumberOfBytesTransfered +// Parameter: LPOVERLAPPED lpOverlapped +// Notes: function passed to the OS as the callback for the alertable overlapped I/O pattern +//************************************ +void __stdcall FileIOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) +{ + // the hEvent field is not used with the alertable pattern, it can used by the title for any data + // in this case we use it to hold a pointer to the class instance that issued the request + // another useful piece of information might be the index of the request instead, this avoid having to compare against all pending requests + OverlappedSample *sample = reinterpret_cast(lpOverlapped->hEvent); + sample->AlertableCompletionRoutine(dwErrorCode, dwNumberOfBytesTransfered, lpOverlapped); +} + +//************************************ +// Method: AlertableCompletionRoutine +// Parameter: uint32_t errorCode +// Parameter: uint32_t numberOfBytesTransfered +// Parameter: OVERLAPPED * overlapped +// Notes: FileIOComplettionRoutine is passed to the OS as a callback, that function then calls into this class member function to resolve the read +//************************************ +void OverlappedSample::AlertableCompletionRoutine(uint32_t errorCode, uint32_t numberOfBytesTransfered, OVERLAPPED *overlapped) +{ + // these parameters are only used in asserts and will give warning for other build configurations + // just always mark them as unreferenced to avoid the warning and thus error in the build + UNREFERENCED_PARAMETER(errorCode); + UNREFERENCED_PARAMETER(numberOfBytesTransfered); + + for (uint32_t i = 0; i < c_maxRequestsInFlight; i++) + { + // since we are using the hEvent field to point to the instance of OverlappedSample we have to query against all pending requests to find the one that finished + if (&(m_pendingOverlap[i].m_overlappedObject) == overlapped) + { + assert(errorCode == ERROR_SUCCESS); + assert(m_pendingOverlap[i].m_requestedReadSize == numberOfBytesTransfered); + m_pendingOverlap[i].m_inUse = false; + m_numRequestsInFlight--; + break; + } + } +} + +//************************************ +// Method: AlertableTypeThreadProc +// Notes: thread procedure used by the alertable overlapped I/O read pattern +//************************************ +void OverlappedSample::AlertableTypeThreadProc() +{ + uint32_t totalReads = 0; + uint32_t totalReadSize = 0; + for (uint32_t readIndex = 0; readIndex < c_numReads; readIndex++) + { + for (uint32_t currentRead = 0; currentRead < m_readSizes[readIndex].second; ) + { + if (m_numRequestsInFlight < c_maxRequestsInFlight) + { + totalReads++; + totalReadSize += m_readSizes[readIndex].first; + currentRead++; + + uint32_t overlapIndex = InitializeBaseOverlappedBlock(m_readSizes[readIndex].first); + + // the hEvent in the overlapped object is not used with completion routines, it can be used for whatever data the title desires + // in this samples case it's used to pass the instance of OverlappedSample that issued the request + m_pendingOverlap[overlapIndex].m_overlappedObject.hEvent = this; + ReadFileIndex readFile = m_pendingOverlap[overlapIndex].m_readFile; + + // ReadFileEx is used for only the alertable pattern, it will always call the completion routine when the requests completes, is canceled, or fails + // it is possible for the completion routine to be called before this function returns so make sure all data is setup correctly before calling + // the same read buffer is used for all pending requests for this sample because we don't actually care about the data read from the file + assert(ReadFileEx(m_openFiles[readFile.first][readFile.second], m_readBuffer, m_pendingOverlap[overlapIndex].m_requestedReadSize, &(m_pendingOverlap[overlapIndex].m_overlappedObject), FileIOCompletionRoutine)); + m_numRequestsInFlight++; + } + else // for the alertable pattern at least one thread in the title must be an alertable state for the completion routine to be called + { // this can be done using SleepEx, WaitForSingleObjectEx, or WaitForMultipleObjectsEx with the last parameter set to TRUE + // if an overlapped request with an attached completion routine completes during the time the thread is suspended it will resume + // the completion routine will be executed on the thread in question and then the thread will continue to sleep or wait + SleepEx(1, TRUE); + } + } + } + while (m_numRequestsInFlight) // all of the requests have to created, wait for the rest of the unfinished to complete + { + SleepEx(1, TRUE); + } + + assert(totalReads == m_totalNumReads); + assert(totalReadSize == m_totalReadSize); + m_typeDone = true; +} diff --git a/XDKSamples/System/AsynchronousIO/Assets/Logo.png b/XDKSamples/System/AsynchronousIO/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/AsynchronousIO/Assets/Logo.png differ diff --git a/XDKSamples/System/AsynchronousIO/Assets/SmallLogo.png b/XDKSamples/System/AsynchronousIO/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/AsynchronousIO/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/AsynchronousIO/Assets/SplashScreen.png b/XDKSamples/System/AsynchronousIO/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/AsynchronousIO/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/AsynchronousIO/Assets/StoreLogo.png b/XDKSamples/System/AsynchronousIO/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/AsynchronousIO/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/AsynchronousIO/Assets/WideLogo.png b/XDKSamples/System/AsynchronousIO/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/AsynchronousIO/Assets/WideLogo.png differ diff --git a/XDKSamples/System/AsynchronousIO/AsynchronousIO.cpp b/XDKSamples/System/AsynchronousIO/AsynchronousIO.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdc9265103ba53fbd3f11691004251150b4d0a66 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/AsynchronousIO.cpp @@ -0,0 +1,220 @@ +//-------------------------------------------------------------------------------------- +// AsynchronousIO.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "AsynchronousIO.h" + +#include "ATGColors.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& /*timer*/) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_frame >= 1) + { + m_overlappedSample.Update(); + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(1920, 1080); + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + std::wstring outputString; + outputString = m_overlappedSample.GetCurrentTypeString(); + uint32_t numDots = (m_timer.GetFrameCount() % 10) + 1; + for (uint32_t i = 0; i < numDots; i++) + { + outputString += L"."; + } + + m_font->DrawString(m_spriteBatch.get(), outputString.c_str(), pos); + + pos.y += m_font->GetLineSpacing() * 1.5f; + + DrawHelpText(pos); + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +void Sample::DrawHelpText(DirectX::XMFLOAT2& pos) +{ + static std::vector helpText = { + L" Asynchronous I/O", + L" Asynchronous I/O is the process of issuing I/O or in the case of this sample file read requests and not expecting the results immediately.", + L" The OS allows multiple asynchronous requests to be ""in-flight"" at a time, up to available resources", + L" The main benefit for using asynchronous I/O is that it allows the OS and the hardware to optimize the order of fulfillment to reduce overall times", + L"", + L" Wait Pattern", + L" The wait pattern issues multiple requests and then waits for any of the requests to finish using WaitForSingleObject or WaitForMultipleObjects.", + L" This has the effect of suspending the thread until a request has finished. The data is then available for the thread to process.", + L"", + L" Query Pattern", + L" The query pattern is similar to the wait pattern, however it uses GetOverlappedResult to query the status of a particular read operation.", + L" This allows the thread to continue processing other work if a request has not completed yet.", + L" The main difference between wait and query is that wait can work on multiple requests at a time while query can only handle one at a time.", + L" They both allow multiple in-flight requests, it's just how the title chooses to continue working while the requests are in-flight", + L"", + L" Alertable Pattern", + L" The alertable pattern uses a completion callback system. The title includes along with a specific request a callback function for when the request completes.", + L" The OS will queue the function call to happen after the request completes and a thread is in an alertable state.", + L" An alertable state is when a thread is suspended but tells the OS that is can be woken to perform other work.", + L" The main way for a thread to enter an alertable state is using either SleepEx, WaitForSingleObjectEx, or WaitForMultipleObjectsEx", + L" A side effect with using this pattern is that the callback function could be called from any thread at any time a thread is in the alertable state.", + }; + + for (uint32_t i = 0; i < helpText.size(); i++) + { + pos.y += m_font->GetLineSpacing() * 1.1f; + m_font->DrawString(m_spriteBatch.get(), helpText[i].c_str(), pos); + } +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/AsynchronousIO/AsynchronousIO.h b/XDKSamples/System/AsynchronousIO/AsynchronousIO.h new file mode 100644 index 0000000000000000000000000000000000000000..fd1a3a18f1c46c012ecb7a5a8f3bc6acf923a37e --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/AsynchronousIO.h @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// AsynchronousIO.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "OverlappedSample.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void DrawHelpText(DirectX::XMFLOAT2& pos); + + OverlappedSample m_overlappedSample; + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + Microsoft::WRL::ComPtr m_background; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; +}; diff --git a/XDKSamples/System/AsynchronousIO/AsynchronousIO.sln b/XDKSamples/System/AsynchronousIO/AsynchronousIO.sln new file mode 100644 index 0000000000000000000000000000000000000000..150d34568bb72194b010935dd743e7ef33f575bf --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/AsynchronousIO.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AsynchronousIO", "AsynchronousIO.vcxproj", "{92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Debug|Durango.ActiveCfg = Debug|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Debug|Durango.Build.0 = Debug|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Debug|Durango.Deploy.0 = Debug|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Profile|Durango.ActiveCfg = Profile|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Profile|Durango.Build.0 = Profile|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Profile|Durango.Deploy.0 = Profile|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Release|Durango.ActiveCfg = Release|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Release|Durango.Build.0 = Release|Durango + {92A8DCAF-9D5A-4ECA-B9D3-7E511C901AAB}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/AsynchronousIO/AsynchronousIO.vcxproj b/XDKSamples/System/AsynchronousIO/AsynchronousIO.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..8cad0a4ced82b928bda47899ba65d38837f83917 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/AsynchronousIO.vcxproj @@ -0,0 +1,230 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + AsynchronousIO + {92a8dcaf-9d5a-4eca-b9d3-7e511c901aab} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\CPUTK;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + true + + + 5.0 + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\CPUTK;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + true + + + 5.0 + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\CPUTK;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + true + + + 5.0 + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + Designer + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/AsynchronousIO/AsynchronousIO.vcxproj.filters b/XDKSamples/System/AsynchronousIO/AsynchronousIO.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..a876827c127598148240f987ca9ceab408bb0be3 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/AsynchronousIO.vcxproj.filters @@ -0,0 +1,82 @@ + + + + + 24cb45c7-ea80-4f37-b4fe-75d671915355 + + + fd75e742-684e-448c-80ea-c322d6ee22b1 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {4ba36794-3f06-49f7-b32c-9119b430df88} + + + {31ca5c82-336f-4695-9a1f-9428a6ac906b} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + + CPU Tool Kit + + + + + + + + Common + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/AsynchronousIO/DeviceResources.cpp b/XDKSamples/System/AsynchronousIO/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..051840a6dab4898c0c5aed915a810f0ac27ad297 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/DeviceResources.cpp @@ -0,0 +1,237 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, bool fastSemantics) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_fastSemantics(fastSemantics) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_fastSemantics) + { + creationFlags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_fastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if (m_fastSemantics && decompressFlags) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/AsynchronousIO/DeviceResources.h b/XDKSamples/System/AsynchronousIO/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..a74ce25c71af7f6b9a766ec071b419b131d991e9 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/DeviceResources.h @@ -0,0 +1,66 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + bool fastSemantics = false); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + bool m_fastSemantics; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/AsynchronousIO/Main.cpp b/XDKSamples/System/AsynchronousIO/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c6ad266a14695eb9e93db44ebe137c5169217f0 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/Main.cpp @@ -0,0 +1,144 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "AsynchronousIO.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH + 1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/AsynchronousIO/OverlappedSample.cpp b/XDKSamples/System/AsynchronousIO/OverlappedSample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ff2efab57d1412fc5cdf3060879458de4749d1f --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/OverlappedSample.cpp @@ -0,0 +1,379 @@ +//-------------------------------------------------------------------------------------- +// OverlappedSample.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "OverlappedSample.h" +#include + +OverlappedSample::OverlappedSample() : + m_currentType(OverlappedType::NULL_TYPE) + , m_workThread(nullptr) + , m_typeDone(true) + , m_numRequestsInFlight(0) + , m_dataFileSizes { + DataFileSizePair(50 * 1024 * 1024, 2), + DataFileSizePair(10 * 1024 * 1024, 4), + DataFileSizePair(5 * 1024 * 1024, 6), + DataFileSizePair(1 * 1024 * 1024, 20), + DataFileSizePair(768 * 1024, 50), + DataFileSizePair(512 * 1024, 100), + DataFileSizePair(256 * 1024, 200), + DataFileSizePair(128 * 1024, 300), + DataFileSizePair(64 * 1024, 500), + DataFileSizePair(32 * 1024, 500) + } + , m_readSizes{ + ReadSizePair(5 * 1024 * 1024, 2), + ReadSizePair(1 * 1024 * 1024, 4), + ReadSizePair(768 * 1024, 6), + ReadSizePair(512 * 1024, 20), + ReadSizePair(256 * 1024, 50), + ReadSizePair(128 * 1024, 100), + ReadSizePair(64 * 1024, 200), + ReadSizePair(32 * 1024, 300), + ReadSizePair(16 * 1024, 500), + ReadSizePair(4 * 1024, 500) + } + , m_totalReadSize(0) + , m_totalNumReads(0) +{ + // all non-buffered (which overlapped requires) reads require the size of the read to be a multiple of 4k + for (uint32_t i = 0; i < c_numReads; i++) + { + m_readSizes[i].first &= ~4095; + m_totalNumReads += m_readSizes[i].second; + m_totalReadSize += m_readSizes[i].first * m_readSizes[i].second; + } + + // all non-buffered (which overlapped requires) reads require the location to be a multiple of 4k + // set the size of the files to be a multiple of 4k, this simplifies some of the math in the sample + for (uint32_t i = 0; i < c_numDataFileSizes; i++) + { + m_dataFileSizes[i].first &= ~4095; + } + memset(m_pendingOverlap, 0xff, sizeof(m_pendingOverlap)); + for (uint32_t i = 0; i < c_maxRequestsInFlight; i++) + { + m_events[i] = INVALID_HANDLE_VALUE; + } +} + +OverlappedSample::~OverlappedSample() +{ + ShutdownCurrentType(); + CloseFiles(); + for (uint32_t i = 0; i < c_maxRequestsInFlight; i++) + { + if (m_events[i] != INVALID_HANDLE_VALUE) + { + CloseHandle(m_events[i]); + } + } + VirtualFree(m_readBuffer, 0, MEM_DECOMMIT); +} + +//************************************ +// Method: CloseFiles +// Notes: Cleanup all of the open files, used when shutting down the sample +//************************************ +void OverlappedSample::CloseFiles() +{ + auto endOuterIter = m_openFiles.end(); + for (auto outerIter = m_openFiles.begin(); outerIter != endOuterIter; ++outerIter) + { + auto endInnerIter = outerIter->end(); + for (auto innerIter = outerIter->begin(); innerIter != endInnerIter; ++innerIter) + { + CloseHandle(*innerIter); + } + } +} + +//************************************ +// Method: Init +// Returns: bool - success or failure +// Notes: Allocates the main memory buffer and allocates the cache of event objects +//************************************ +bool OverlappedSample::Init() +{ + m_readBuffer = VirtualAlloc(nullptr, m_dataFileSizes[0].first, MEM_COMMIT, PAGE_READWRITE); + if (!m_readBuffer) + return false; + for (uint32_t i = 0; i < c_maxRequestsInFlight; i++) + { + // use manual reset events for overlapped requests, this guarantees against missing finished notifications. + m_events[i] = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (m_events[i] == INVALID_HANDLE_VALUE) + return false; + // since there are only c_maxRequestsInFlight at a time we can bind event objects to overlapped objects + m_pendingOverlap[i].m_overlappedObject.hEvent = m_events[i]; + m_pendingOverlap[i].m_inUse = false; + } + return true; +} + +//************************************ +// Method: FindOpenOverlappedBlock +// Returns: uint32_t - an unused entry in the pending request list +//************************************ +uint32_t OverlappedSample::FindOpenOverlappedBlock() +{ + for (uint32_t i = 0; i < c_maxRequestsInFlight; i++) + { + if (!m_pendingOverlap[i].m_inUse) + return i; + } + return UINT32_MAX; +} + +//************************************ +// Method: PickReadFile +// Returns: ReadFileIndex - pair used as index into 2d array m_openFiles +// Parameter: uint32_t readSize - How many bytes need to be available in the file +//************************************ +OverlappedSample::ReadFileIndex OverlappedSample::PickReadFile(uint32_t readSize) +{ + ReadFileIndex toret(UINT32_MAX, UINT32_MAX); + + assert(m_openFiles.size()); + for (toret.first = 0; toret.first < c_numDataFileSizes; toret.first++) + { + if (m_dataFileSizes[toret.first].first < readSize) + { + toret.first--; + break; + } + } + if (toret.first != 0) + toret.first = std::rand() % toret.first; + assert(m_openFiles[toret.first].size()); + toret.second = std::rand() % m_openFiles[toret.first].size(); + return toret; +} + +//************************************ +// Method: PickReadLocation +// Returns: uint32_t - the base location in the file to start the read +// Parameter: ReadFileIndex readFile - which file to read from +// Parameter: uint32_t readSize - size of the read request +//************************************ +uint32_t OverlappedSample::PickReadLocation(ReadFileIndex readFile, uint32_t readSize) +{ + assert(readFile.first != UINT32_MAX); + assert(readFile.second != UINT32_MAX); + assert(m_dataFileSizes[readFile.first].first >= readSize); + + if (m_dataFileSizes[readFile.first].first == readSize) + return 0; + + return (std::rand() % (m_dataFileSizes[readFile.first].first - readSize)) & ~4095; // require 4k alignment for file location for overlapped +} + +//************************************ +// Method: InitializeBaseOverlappedBlock +// Returns: uint32_t - which index into m_pendingOverlap was setup +// Notes: setup a pending overlap block with common data for each pattern +// will also pick the file and read size for this request +// all patterns use an OVERLAPPED structure which contains the read location +//************************************ +uint32_t OverlappedSample::InitializeBaseOverlappedBlock(uint32_t readSize) +{ + // all non-buffered (which overlapped requires) reads require the size of the read to be a multiple of 4k + assert((readSize % 4096) == 0); + uint32_t overlapIndex = FindOpenOverlappedBlock(); + assert(overlapIndex != UINT32_MAX); + ReadFileIndex readFile = PickReadFile(readSize); + uint32_t readLocation = PickReadLocation(readFile, readSize); + + // all non-buffered (which overlapped requires) reads require the location to be a multiple of 4k + assert((readLocation % 4096) == 0); + m_pendingOverlap[overlapIndex].m_inUse = true; + m_pendingOverlap[overlapIndex].m_readFile = readFile; + m_pendingOverlap[overlapIndex].m_requestedReadSize = readSize; + + // By default all fields of the OVERLAPPED structure should be zero except for the Offset for the read in the file + // hEvent has different meanings based on the pattern being used and is set by the caller of this function + m_pendingOverlap[overlapIndex].m_overlappedObject.Internal = 0; + m_pendingOverlap[overlapIndex].m_overlappedObject.InternalHigh = 0; + m_pendingOverlap[overlapIndex].m_overlappedObject.Offset = readLocation; + m_pendingOverlap[overlapIndex].m_overlappedObject.OffsetHigh = 0; + + return overlapIndex; +} + +//************************************ +// Method: CreateAndOpenFilesThreadProc +// Notes: create all of the data files used for the sample, will reopen the files for overlapped operation +//************************************ +void OverlappedSample::CreateAndOpenFilesThreadProc() +{ + // Make sure any cruft for open files are closed before recreating and reopening the files + CloseFiles(); + + uint32_t *baseDataAddress32 = reinterpret_cast (m_readBuffer); + // just assume the first entry is the largest. + for (uint32_t i = 0; i < m_dataFileSizes[0].first / sizeof(uint32_t); i++) + { + baseDataAddress32[i] = i; + } + + uint64_t totalFileSize = 0; + + // This sample creates all of the data files each time it's run. + // This allows easy changes to the m_dataFileSizes and m_numDataFilesPerSize for testing purposes + m_openFiles.resize(c_numDataFileSizes); + for (uint32_t fileIndexSize = 0; fileIndexSize < c_numDataFileSizes; fileIndexSize++) + { + m_openFiles[fileIndexSize].reserve(m_dataFileSizes[fileIndexSize].second); + for (uint32_t fileIndex = 0; fileIndex < m_dataFileSizes[fileIndexSize].second; fileIndex++) + { + wchar_t fileName[128]; + totalFileSize += m_dataFileSizes[fileIndexSize].first; + swprintf_s(fileName, 128, L"d:\\dataFile_%d_%d.dat", fileIndexSize, fileIndex); + HANDLE curFile; + CREATEFILE2_EXTENDED_PARAMETERS params; + memset(¶ms, 0, sizeof(params)); + params.dwSize = sizeof(params); + params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + // It's recommended to always use FILE_FLAG_NO_BUFFERING if possible + // This avoids the pollution of the small file cache used on Xbox and let's it store MFT data for efficient file opens + params.dwFileFlags = FILE_FLAG_NO_BUFFERING; + curFile = CreateFile2(fileName, GENERIC_ALL, 0, CREATE_ALWAYS, ¶ms); + if (curFile == INVALID_HANDLE_VALUE) + { + m_typeDone = true; + return; + } + DWORD bytesWritten; + if (!WriteFile(curFile, m_readBuffer, m_dataFileSizes[fileIndexSize].first, &bytesWritten, nullptr)) + { + m_typeDone = true; // This will exit the thread and cause the system to try again next pass + return; + } + CloseHandle(curFile); + + // reopen the file for overlapped operation with FILE_FLAG_OVERLAPPED + params.dwFileFlags = FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED; + curFile = CreateFile2(fileName, GENERIC_ALL, 0, OPEN_EXISTING, ¶ms); + m_openFiles[fileIndexSize].push_back(curFile); + } + } + + m_typeDone = true; +} + +//************************************ +// Method: ShutdownCurrentType +// Notes: wait for the worker thread to shutdown and then clean it up +//************************************ +void OverlappedSample::ShutdownCurrentType() +{ + if (m_workThread) + { + m_workThread->join(); + delete m_workThread; + m_workThread = nullptr; + } +} + +//************************************ +// Method: StartIndividualType +// Returns: bool - success or failure +// Notes: based on m_currentType create a thread with the corresponding thread procedure +//************************************ +bool OverlappedSample::StartIndividualType() +{ + m_typeDone = false; + std::function threadFunc; + + switch (m_currentType) + { + case OverlappedType::CREATING_FILES: + threadFunc = &OverlappedSample::CreateAndOpenFilesThreadProc; + break; + case OverlappedType::EVENT: + threadFunc = &OverlappedSample::EventTypeThreadProc; + break; + case OverlappedType::QUERY: + threadFunc = &OverlappedSample::QueryTypeThreadProc; + break; + case OverlappedType::ALERTABLE: + threadFunc = &OverlappedSample::AlertableTypeThreadProc; + break; + default: + return false; + } + + m_workThread = new std::thread(threadFunc, this); + return true; +} + +//************************************ +// Method: Update +// Returns: bool - success or failure on the update, really only used for initialization +// Notes: called every frame by the main sample, will rotate through the patterns as they finish +//************************************ +bool OverlappedSample::Update() +{ + if (m_events[0] == INVALID_HANDLE_VALUE) + { + if (!Init()) + return false; + } + + if (m_typeDone) + { + ShutdownCurrentType(); + } + + if (m_workThread == nullptr) + { + switch (m_currentType) + { + case OverlappedType::NULL_TYPE: + m_currentType = OverlappedType::CREATING_FILES; + break; + case OverlappedType::CREATING_FILES: + m_currentType = OverlappedType::EVENT; + break; + case OverlappedType::EVENT: + m_currentType = OverlappedType::QUERY; + break; + case OverlappedType::QUERY: + m_currentType = OverlappedType::ALERTABLE; + break; + case OverlappedType::ALERTABLE: + m_currentType = OverlappedType::EVENT; + break; + } + return StartIndividualType(); + } + return true; +} + +//************************************ +// Method: GetCurrentTypeString +// Returns: std::wstring - matching string for the current pattern running, used for display on the screen +//************************************ +std::wstring OverlappedSample::GetCurrentTypeString() const +{ + switch (m_currentType) + { + case OverlappedType::NULL_TYPE: + return L"Not Started"; + case OverlappedType::CREATING_FILES: + return L"Creating Files"; + case OverlappedType::EVENT: + return L"Running Event Based"; + case OverlappedType::QUERY: + return L"Running Query Based"; + case OverlappedType::ALERTABLE: + return L"Running Alertable Based"; + } + assert(false); + return L"Unknown Type"; +} diff --git a/XDKSamples/System/AsynchronousIO/OverlappedSample.h b/XDKSamples/System/AsynchronousIO/OverlappedSample.h new file mode 100644 index 0000000000000000000000000000000000000000..ce85a1b61347eb3654430c3a1902cfa4f17181d0 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/OverlappedSample.h @@ -0,0 +1,108 @@ +//-------------------------------------------------------------------------------------- +// OverlappedSample.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once +#include +#include +#include +#include +#include +#include + +class OverlappedSample +{ +public: + static const uint32_t c_maxRequestsInFlight = 12; + static const uint32_t c_numDataFileSizes = 10; + static const uint32_t c_numReads = 10; + enum class OverlappedType + { + NULL_TYPE, + CREATING_FILES, // create and open each of the data files + EVENT, // use the event pattern for overlapped I/O, each request has an associated event object that can be used with WaitForSingleObject + QUERY, // use the query pattern for overlapped I/O, call GetOverlappedResult to check on a request until it is complete + ALERTABLE, // use the alert pattern for overlapped I/O, a completion callback is used and called by the OS when the thread is in an alertable state + }; + +private: + + ////////////////////////////////////////////////////////////////////////// + // + // Shared data and interfaces between each overlapped read pattern + // + ////////////////////////////////////////////////////////////////////////// + typedef std::pair ReadFileIndex; // first is which size file, second is which file within size + typedef std::pair DataFileSizePair; // first is size of the file, second is how many files of that size + typedef std::pair ReadSizePair; // first is how many bytes to read, second is how many times to perform this read + struct PendingOverlap + { + bool m_inUse; + ReadFileIndex m_readFile; + uint32_t m_requestedReadSize; + OVERLAPPED m_overlappedObject; // all OVERLAPPED objects must remain valid during the entire time the request in flight, they can be reused though + }; + + void *m_readBuffer; // one buffer is shared for all read requests since this sample doesn't actually care about the loaded data + uint32_t m_numRequestsInFlight; // how many pending requests are currently active + std::atomic m_typeDone; // set by the worker thread when it's done loading data so the sample can switch to the next one + std::thread *m_workThread; // thread performing the read requests and checking for completed requests + OverlappedType m_currentType; // which type of pattern is currently running + + HANDLE m_events[c_maxRequestsInFlight]; // preallocated events to use for event and query based patterns + PendingOverlap m_pendingOverlap[c_maxRequestsInFlight]; // control data for each pending request, reused for new pending requests + + std::array m_dataFileSizes; // first is size of the file, second is how many files of that size + std::array m_readSizes; // first is how many bytes to read, second is how many times to perform this read + + std::vector> m_openFiles; // 2d array for all of the open files, based on [file size][index at that size] + + uint32_t m_totalReadSize; // sum of the size of all reads, used for internal validation + uint32_t m_totalNumReads; // sum of the total number of reads, used for internal validation + + bool Init(); // allocate the events and memory buffers + void CloseFiles(); // cleanup the open files + bool StartIndividualType(); // create the proper thread based on which type of overlapped pattern is being used + void ShutdownCurrentType(); // cleanup the executing thread + void CreateAndOpenFilesThreadProc(); // using the data in m_dataFileSizes and m_numDataFilesPerSize create the data files then open them for testing + + uint32_t InitializeBaseOverlappedBlock(uint32_t readSize); // find and setup an unused PendingOverlap block with data shared by all patterns + uint32_t FindOpenOverlappedBlock(); // returns an unused member of m_pendingOverlap + ReadFileIndex PickReadFile(uint32_t readSize); // find a valid file to use for a specific read size, is large enough + uint32_t PickReadLocation(ReadFileIndex readFile, uint32_t readSize); // find a valid location in the requested file that can be used for the requested read size + + ////////////////////////////////////////////////////////////////////////// + // + // Data and Interfaces unique to using a wait pattern on overlapped I/O + // + ////////////////////////////////////////////////////////////////////////// + void EventTypeThreadProc(); + void WaitForEventOverlappedToFinish(); + + ////////////////////////////////////////////////////////////////////////// + // + // Data and Interfaces unique to using a query pattern on overlapped I/O + // + ////////////////////////////////////////////////////////////////////////// + void QueryTypeThreadProc(); + void QueryForOverlappedFinished(); + + ////////////////////////////////////////////////////////////////////////// + // + // Data and Interfaces unique to using an alertable/callback pattern on overlapped I/O + // + ////////////////////////////////////////////////////////////////////////// + friend void __stdcall FileIOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped); + void AlertableTypeThreadProc(); + void AlertableCompletionRoutine(uint32_t errorCode, uint32_t numberOfBytesTransfered, OVERLAPPED *overlapped); + +public: + OverlappedSample(); + ~OverlappedSample(); + + bool Update(); + std::wstring GetCurrentTypeString() const; +}; diff --git a/XDKSamples/System/AsynchronousIO/Package.appxmanifest b/XDKSamples/System/AsynchronousIO/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..102af7cfb2329548aafeb886468d55904fce8903 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + AsynchronousIO + Xbox Advanced Technology Group + Assets\StoreLogo.png + AsynchronousIO + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/AsynchronousIO/QueryOverlapped.cpp b/XDKSamples/System/AsynchronousIO/QueryOverlapped.cpp new file mode 100644 index 0000000000000000000000000000000000000000..61ba0fca65443bdccb6115d0422ac6a227d7df41 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/QueryOverlapped.cpp @@ -0,0 +1,104 @@ +//-------------------------------------------------------------------------------------- +// QueryOverlapped.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "OverlappedSample.h" + +//************************************ +// Method: QueryForOverlappedFinished +// Notes: goes through and queries the current pending file operations to see which are completed +//************************************ +void OverlappedSample::QueryForOverlappedFinished() +{ + for (uint32_t i = 0; i < c_maxRequestsInFlight; i++) + { + if (m_pendingOverlap[i].m_inUse) + { + DWORD actuallyTransferred; + ReadFileIndex file = m_pendingOverlap[i].m_readFile; + // the query pattern uses GetOverlappedResult directly as opposed to WaitFor###Object on an event + // this might be useful for a title that is performing other work on a file loading thread + // it can quickly go through and check the status of pending requests and continue doing other work if none have completed + // at any point in time the title can check the status of a particular request, with the final parameter FALSE this can be fairly quick + if (GetOverlappedResult(m_openFiles[file.first][file.second], &m_pendingOverlap[i].m_overlappedObject, &actuallyTransferred, FALSE)) + { + assert(m_pendingOverlap[i].m_requestedReadSize == actuallyTransferred); + m_pendingOverlap[i].m_inUse = false; + m_numRequestsInFlight--; + } + else // if GetOverlappedResult returns FALSE that means either an error or the data is not available yet + { // for this sample we only handle the case where data is not available yet + assert(GetLastError() == ERROR_IO_INCOMPLETE); + } + + // always make sure the event being used for the query pattern is not signaled to avoid false notification before reusing it + ResetEvent(m_pendingOverlap[i].m_overlappedObject.hEvent); + } + } +} + +//************************************ +// Method: QueryTypeThreadProc +// Notes: thread procedure used for the query overlapped I/O pattern +//************************************ +void OverlappedSample::QueryTypeThreadProc() +{ + uint32_t totalReads = 0; + uint32_t totalReadSize = 0; + for (uint32_t readIndex = 0; readIndex < m_readSizes.size (); readIndex++) + { + for (uint32_t currentRead = 0; currentRead < m_readSizes[readIndex].second; ) + { + if (m_numRequestsInFlight < c_maxRequestsInFlight) + { + totalReads++; + totalReadSize += m_readSizes[readIndex].first; + currentRead++; + + uint32_t overlapIndex = InitializeBaseOverlappedBlock(m_readSizes[readIndex].first); + + // need to use an event with query as well as with the wait pattern + // this is without the event the call to GetOverlappedResults will use notification based on the file handle itself + // with multiple requests in flight for a file this can result in confusion on exactly which request finished + m_pendingOverlap[overlapIndex].m_overlappedObject.hEvent = m_events[overlapIndex]; + + ReadFileIndex readFile = m_pendingOverlap[overlapIndex].m_readFile; + DWORD actuallyTransferred; + + // the variable that receives the number of bytes actually read is always useful when calling ReadFile even for overlapped operations + // if the data is available immediately it will contain how much was read and avoid another call to GetOverlappedResult to query for the value + // the same read buffer is used for all pending requests for this sample because we don't actually care about the data read from the file + if (!ReadFile(m_openFiles[readFile.first][readFile.second], m_readBuffer, m_pendingOverlap[overlapIndex].m_requestedReadSize, &actuallyTransferred, &(m_pendingOverlap[overlapIndex].m_overlappedObject))) + { + // if the OS actually starts an asynchronous operation then the error ERROR_IO_PENDING will be returned + // this is not an actual error even though ReadFile returned false + assert(GetLastError() == ERROR_IO_PENDING); + m_numRequestsInFlight++; + } + else // asynchronous call to ReadFile was converted to a synchronous call by the OS, data is available now + { // this won't happen on Xbox due to FILE_FLAG_NO_BUFFERED, the small file cache, and no read ahead + // it's recommended to include this check for titles that also execute on PC where it can happen especially due to read ahead + assert(actuallyTransferred == m_pendingOverlap[overlapIndex].m_requestedReadSize); + m_pendingOverlap[overlapIndex].m_inUse = false; + } + } + else + { + QueryForOverlappedFinished(); + } + } + } + while (m_numRequestsInFlight) // all of the requests have to created, wait for the rest of the unfinished to complete + { + QueryForOverlappedFinished(); + } + + assert(totalReads == m_totalNumReads); + assert(totalReadSize == m_totalReadSize); + + m_typeDone = true; +} diff --git a/XDKSamples/System/AsynchronousIO/Readme.docx b/XDKSamples/System/AsynchronousIO/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..85ace373ae42eae30f89320760893b5e09739e01 Binary files /dev/null and b/XDKSamples/System/AsynchronousIO/Readme.docx differ diff --git a/XDKSamples/System/AsynchronousIO/StepTimer.h b/XDKSamples/System/AsynchronousIO/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/AsynchronousIO/Telemetry.h b/XDKSamples/System/AsynchronousIO/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/AsynchronousIO/WaitOverlapped.cpp b/XDKSamples/System/AsynchronousIO/WaitOverlapped.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a40696f410943b6b46a821fbb1a0d2a9f9df6534 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/WaitOverlapped.cpp @@ -0,0 +1,123 @@ +//-------------------------------------------------------------------------------------- +// WaitOverlapped.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "OverlappedSample.h" + +//************************************ +// Method: WaitForEventOverlappedToFinish +// Notes: Main routine that waits for any event pattern overlapped I/O to complete +//************************************ +void OverlappedSample::WaitForEventOverlappedToFinish() +{ + // check until none are finished + bool foundFirstOne = false; + for (;;) + { + if (m_numRequestsInFlight == 0) + return; + + // we only want to wait for one request to finish versus all of the pending however multiple could complete at the same time + // because of this we need to sit in a loop calling WaitForMultipleObjects until none are marked as finished + // so have a timeout on the wait of either 0 or forever depending on if we're waiting for the initial request to complete + // we actually can use the entire array of cached events. the events not currently bound to an I/O operation will not signal + // so we won't get spurious wakeups. + DWORD waitRet = WaitForMultipleObjects(c_maxRequestsInFlight, m_events, FALSE, foundFirstOne ? 0 : INFINITE); + + // none are complete, however at least one completed during this call since the first call uses a timeout of 0 + // returning allows EventTypeThreadProc to issue more requests up to c_maxRequestsInFlight + if (waitRet == WAIT_TIMEOUT) + return; + foundFirstOne = true; + uint32_t whichFinished = waitRet - WAIT_OBJECT_0; + assert(whichFinished < c_maxRequestsInFlight); + DWORD actuallyTransferred; + ReadFileIndex file = m_pendingOverlap[whichFinished].m_readFile; + + // now that we know which request finished we need to check that all data was actually read which is what GetOverlappedResult will return + // we don't need GetOverlappedResult to wait for the request to finish so pass FALSE for the final parameter + // it is possible that other requests finished as well by the time this thread resumed from the WaitForMultipleObjects + // an option would be to use GetOverlappedResult to iterate through all pending operations, you would do the entire list since any of the operations could + // have finished by the time the thread gets to this section. could also just do from the signaled to the end and pick up the others the next time through the loop + // this sample explicitly just catches one at a time through the loop since this is focusing on using WaitForMultipleObjects to get notification. + // see QueryOverlapped.cpp for a demonstration of iterating through the list of pending operations. the readme also has a discussion on mixing the two patterns + if (!GetOverlappedResult(m_openFiles[file.first][file.second], &m_pendingOverlap[whichFinished].m_overlappedObject, &actuallyTransferred, FALSE)) + { + assert(false); + } + else + { + assert(m_pendingOverlap[whichFinished].m_requestedReadSize == actuallyTransferred); + } + // always make sure the event being used for the wait pattern is not signaled to avoid false notification before reusing it + ResetEvent(m_pendingOverlap[whichFinished].m_overlappedObject.hEvent); + + m_pendingOverlap[whichFinished].m_inUse = false; + m_numRequestsInFlight--; + } +} + +//************************************ +// Method: EventTypeThreadProc +// Notes: thread proc for event pattern overlapped I/O. keeps requesting overlapped reads while the number in flight is less than the maximum allowed +// when the maximum is hit wait for some of them to complete +//************************************ +void OverlappedSample::EventTypeThreadProc() +{ + uint32_t totalReads = 0; + uint32_t totalReadSize = 0; + for (uint32_t readIndex = 0; readIndex < c_numReads; readIndex++) + { + for (uint32_t currentRead = 0; currentRead < m_readSizes[readIndex].second; ) + { + if (m_numRequestsInFlight < c_maxRequestsInFlight) + { + totalReads++; + totalReadSize += m_readSizes[readIndex].first; + currentRead++; + + uint32_t overlapIndex = InitializeBaseOverlappedBlock(m_readSizes[readIndex].first); + + // The wait pattern requires an associated event that can be used in WaitForSingleObject or WaitForMultipleObjects + m_pendingOverlap[overlapIndex].m_overlappedObject.hEvent = m_events[overlapIndex]; + + ReadFileIndex readFile = m_pendingOverlap[overlapIndex].m_readFile; + DWORD actuallyTransferred; + + // the variable that receives the number of bytes actually read is always useful when calling ReadFile even for overlapped operations + // if the data is available immediately it will contain how much was read and avoid another call to GetOverlappedResult to query for the value + // the same read buffer is used for all pending requests for this sample because we don't actually care about the data read from the file + if (!ReadFile(m_openFiles[readFile.first][readFile.second], m_readBuffer, m_pendingOverlap[overlapIndex].m_requestedReadSize, &actuallyTransferred, &(m_pendingOverlap[overlapIndex].m_overlappedObject))) + { + // if the OS actually starts an asynchronous operation then the error ERROR_IO_PENDING will be returned + // this is not an actual error even though ReadFile returned false + assert(GetLastError() == ERROR_IO_PENDING); + m_numRequestsInFlight++; + } + else // asynchronous call to ReadFile was converted to a synchronous call by the OS, data is available now + { // this won't happen on Xbox due to FILE_FLAG_NO_BUFFERED, the small file cache, and no read ahead + // it's recommended to include this check for titles that also execute on PC where it can happen especially due to read ahead + assert(actuallyTransferred == m_pendingOverlap[overlapIndex].m_requestedReadSize); + m_pendingOverlap[overlapIndex].m_inUse = false; + } + } + else // at the maximum number of requests in flight so wait for some of them to complete + { // this could happen on any thread desired, for example one thread is constantly adding requests to a queue + // and another thread is waiting for requests to finish + WaitForEventOverlappedToFinish(); + } + } + } + while (m_numRequestsInFlight) // all of the requests have to created, wait for the rest of the unfinished to complete + { + WaitForEventOverlappedToFinish(); + } + + assert(totalReads == m_totalNumReads); + assert(totalReadSize == m_totalReadSize); + m_typeDone = true; +} diff --git a/XDKSamples/System/AsynchronousIO/pch.cpp b/XDKSamples/System/AsynchronousIO/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/AsynchronousIO/pch.h b/XDKSamples/System/AsynchronousIO/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..ec9a6272beba2123c3e556e63a995c7386296b40 --- /dev/null +++ b/XDKSamples/System/AsynchronousIO/pch.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "SimpleMath.h" +#include "DDSTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} diff --git a/XDKSamples/System/Collision/Assets/Logo.png b/XDKSamples/System/Collision/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/Collision/Assets/Logo.png differ diff --git a/XDKSamples/System/Collision/Assets/SmallLogo.png b/XDKSamples/System/Collision/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/Collision/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/Collision/Assets/SplashScreen.png b/XDKSamples/System/Collision/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/Collision/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/Collision/Assets/StoreLogo.png b/XDKSamples/System/Collision/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/Collision/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/Collision/Assets/WideLogo.png b/XDKSamples/System/Collision/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/Collision/Assets/WideLogo.png differ diff --git a/XDKSamples/System/Collision/Collision.cpp b/XDKSamples/System/Collision/Collision.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4991b7dc7429a3bd546f0ad198b2413d10ca84f4 --- /dev/null +++ b/XDKSamples/System/Collision/Collision.cpp @@ -0,0 +1,628 @@ +//-------------------------------------------------------------------------------------- +// Collision.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Collision.h" + +#include "ATGColors.h" +#include "DebugDraw.h" + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +namespace +{ + static const float c_cameraSpacing = 50.f; + + //-------------------------------------------------------------------------------------- + // Returns the color based on the collision result and the group number. + // Frustum tests (group 0) return 0, 1, or 2 for outside, partially inside, and fully inside; + // all other tests return 0 or 1 for no collision or collision. + //-------------------------------------------------------------------------------------- + inline XMVECTOR GetCollisionColor(ContainmentType collision, int groupnumber) + { + // special case: a value of 1 for groups 1 and higher needs to register as a full collision + if (groupnumber >= 3 && collision > 0) + collision = CONTAINS; + + switch (collision) + { + case DISJOINT: return ATG::Colors::Green; + case INTERSECTS: return ATG::Colors::Orange; + case CONTAINS: + default: return ATG::Colors::White; + } + } + + const wchar_t* g_SampleTitle = L"Collision sample"; + const wchar_t* g_SampleDescription = L"This sample demonstrates DirectXMath's collision types"; + const ATG::HelpButtonAssignment g_HelpButtons[] = { + { ATG::HelpID::MENU_BUTTON, L"Toggle help" }, + { ATG::HelpID::VIEW_BUTTON, L"Exit" }, + { ATG::HelpID::RIGHT_STICK, L"Orbit X/Y" }, + { ATG::HelpID::RIGHT_STICK_CLICK, L"Reset view" }, + { ATG::HelpID::DPAD_LEFT, L"Ray" }, + { ATG::HelpID::DPAD_RIGHT, L"Axis-aligned box" }, + { ATG::HelpID::DPAD_UP, L"Frustum" }, + { ATG::HelpID::DPAD_DOWN, L"Oriented box" }, + }; +} + +Sample::Sample() : + m_frame(0), + m_showHelp(false) +{ + m_deviceResources = std::make_unique(); + + m_camera.SetRadius(25.f); + m_camera.SetSensitivity(5.f, 1.f, 10.f, .25f); + m_camera.SetProjectionParameters(XM_PI / 4.f, 0.1f, 1000.f); + m_camera.SetFlags(DX::OrbitCamera::c_FlagsDisableTranslation + | DX::OrbitCamera::c_FlagsDisableRollZ + | DX::OrbitCamera::c_FlagsArrowKeysOrbit + | DX::OrbitCamera::c_FlagsDisableRadiusControl + | DX::OrbitCamera::c_FlagsDisableSensitivityControl); + + m_help = std::make_unique(g_SampleTitle, g_SampleDescription, g_HelpButtons, _countof(g_HelpButtons)); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + InitializeObjects(); + + SetViewForGroup(0); + + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + // Update position of collision objects. + Animate(timer.GetTotalSeconds()); + + // Compute collisions. + Collide(); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (m_gamePadButtons.menu == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = !m_showHelp; + } + else if (m_showHelp && m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + m_showHelp = false; + } + else if (!m_showHelp) + { + m_camera.Update(elapsedTime, pad); + + if (m_gamePadButtons.dpadUp == GamePad::ButtonStateTracker::PRESSED) + { + SetViewForGroup(0); + } + else if (m_gamePadButtons.dpadRight == GamePad::ButtonStateTracker::PRESSED) + { + SetViewForGroup(1); + } + else if (m_gamePadButtons.dpadDown == GamePad::ButtonStateTracker::PRESSED) + { + SetViewForGroup(2); + } + else if (m_gamePadButtons.dpadLeft == GamePad::ButtonStateTracker::PRESSED) + { + SetViewForGroup(3); + } + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + if (m_showHelp) + { + // Draw help screen. + m_help->Render(); + } + else + { + context->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF); + context->OMSetDepthStencilState(m_states->DepthNone(), 0); + context->RSSetState(m_states->CullNone()); + + m_effect->SetView(m_camera.GetView()); + m_effect->SetProjection(m_camera.GetProjection()); + m_effect->Apply(context); + + context->IASetInputLayout(m_layout.Get()); + + m_batch->Begin(); + + // Draw ground planes + for (size_t i = 0; i < c_groupCount; ++i) + { + static const XMVECTORF32 s_xAxis = { 20.f, 0.f, 0.f, 0.f }; + static const XMVECTORF32 s_yAxis = { 0.f, 0.f, 20.f, 0.f }; + + static const XMVECTORF32 s_Offset = { 0.f, 10.f, 0.f, 0.f }; + XMVECTOR origin = m_cameraOrigins[i] - s_Offset; + + DX::DrawGrid(m_batch.get(), s_xAxis, s_yAxis, origin, 20, 20, ATG::Colors::OffWhite); + } + + // Draw primary collision objects in white + DX::Draw(m_batch.get(), m_primaryFrustum, ATG::Colors::Blue); + DX::Draw(m_batch.get(), m_primaryAABox, ATG::Colors::Blue); + DX::Draw(m_batch.get(), m_primaryOrientedBox, ATG::Colors::Blue); + + { + XMVECTOR direction = XMVectorScale(m_primaryRay.direction, 10.0f); + DX::DrawRay(m_batch.get(), m_primaryRay.origin, direction, false, ATG::Colors::LightGrey); + DX::DrawRay(m_batch.get(), m_primaryRay.origin, direction, false, ATG::Colors::White); + } + + // Draw secondary collision objects in colors based on collision results + for (int i = 0; i < c_groupCount; ++i) + { + const CollisionSphere& sphere = m_secondarySpheres[i]; + XMVECTOR c = GetCollisionColor(sphere.collision, i); + DX::Draw(m_batch.get(), sphere.sphere, c); + + const CollisionBox& obox = m_secondaryOrientedBoxes[i]; + c = GetCollisionColor(obox.collision, i); + DX::Draw(m_batch.get(), obox.obox, c); + + const CollisionAABox& aabox = m_secondaryAABoxes[i]; + c = GetCollisionColor(aabox.collision, i); + DX::Draw(m_batch.get(), aabox.aabox, c); + + const CollisionTriangle& tri = m_secondaryTriangles[i]; + c = GetCollisionColor(tri.collision, i); + DX::DrawTriangle(m_batch.get(), tri.pointa, tri.pointb, tri.pointc, c); + } + + // Draw results of ray-object intersection, if there was a hit this frame + if (m_rayHitResultBox.collision != DISJOINT) + DX::Draw(m_batch.get(), m_rayHitResultBox.aabox, ATG::Colors::Orange); + + m_batch->End(); + + auto rect = m_deviceResources->GetOutputSize(); + + auto safeRect = Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + m_sprites->Begin(); + + m_font->DrawString(m_sprites.get(), m_name.c_str(), XMFLOAT2(float(safeRect.left), float(safeRect.top)), ATG::Colors::White); + + m_sprites->End(); + } + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_camera.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_states = std::make_unique(device); + + m_batch = std::make_unique>(context); + + m_sprites = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + + m_effect = std::make_unique(device); + m_effect->SetVertexColorEnabled(true); + + { + void const* shaderByteCode; + size_t byteCodeLength; + + m_effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); + + DX::ThrowIfFailed( + device->CreateInputLayout( + VertexPositionColor::InputElements, VertexPositionColor::InputElementCount, + shaderByteCode, byteCodeLength, + m_layout.ReleaseAndGetAddressOf())); + } + + // Set help device context. + m_help->RestoreDevice(context); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto output = m_deviceResources->GetOutputSize(); + + m_camera.SetWindow(output.right - output.left, output.bottom - output.top); + + // Set help rendering size. + m_help->SetWindow(output); +} +#pragma endregion + +void Sample::InitializeObjects() +{ + const XMVECTOR c_zero = XMVectorZero(); + + // Set up the primary frustum object from a D3D projection matrix + // NOTE: This can also be done on your camera's projection matrix. The projection + // matrix built here is somewhat contrived so it renders well. + XMMATRIX xmProj = XMMatrixPerspectiveFovLH(XM_PIDIV4, 1.77778f, 0.5f, 10.0f); + BoundingFrustum::CreateFromMatrix(m_primaryFrustum, xmProj); + m_primaryFrustum.Origin.z = -7.0f; + m_cameraOrigins[0] = c_zero; + + // Set up the primary axis aligned box + m_primaryAABox.Center = XMFLOAT3(c_cameraSpacing, 0, 0); + m_primaryAABox.Extents = XMFLOAT3(5, 5, 5); + m_cameraOrigins[1] = Vector3(c_cameraSpacing, 0, 0); + + // Set up the primary oriented box with some rotation + m_primaryOrientedBox.Center = XMFLOAT3(-c_cameraSpacing, 0, 0); + m_primaryOrientedBox.Extents = XMFLOAT3(5, 5, 5); + XMStoreFloat4(&m_primaryOrientedBox.Orientation, XMQuaternionRotationRollPitchYaw(XM_PIDIV4, XM_PIDIV4, 0)); + m_cameraOrigins[2] = Vector3(-c_cameraSpacing, 0, 0); + + // Set up the primary ray + m_primaryRay.origin = Vector3(0, 0, c_cameraSpacing); + m_primaryRay.direction = Vector3::UnitZ; + m_cameraOrigins[3] = Vector3(0, 0, c_cameraSpacing); + + // Initialize all of the secondary objects with default values + for (size_t i = 0; i < c_groupCount; i++) + { + m_secondarySpheres[i].sphere.Radius = 1.0f; + m_secondarySpheres[i].sphere.Center = XMFLOAT3(0, 0, 0); + m_secondarySpheres[i].collision = DISJOINT; + + m_secondaryOrientedBoxes[i].obox.Center = XMFLOAT3(0, 0, 0); + m_secondaryOrientedBoxes[i].obox.Extents = XMFLOAT3(0.5f, 0.5f, 0.5f); + m_secondaryOrientedBoxes[i].obox.Orientation = XMFLOAT4(0, 0, 0, 1); + m_secondaryOrientedBoxes[i].collision = DISJOINT; + + m_secondaryAABoxes[i].aabox.Center = XMFLOAT3(0, 0, 0); + m_secondaryAABoxes[i].aabox.Extents = XMFLOAT3(0.5f, 0.5f, 0.5f); + m_secondaryAABoxes[i].collision = DISJOINT; + + m_secondaryTriangles[i].pointa = c_zero; + m_secondaryTriangles[i].pointb = c_zero; + m_secondaryTriangles[i].pointc = c_zero; + m_secondaryTriangles[i].collision = DISJOINT; + } + + // Set up ray hit result box + m_rayHitResultBox.aabox.Center = XMFLOAT3(0, 0, 0); + m_rayHitResultBox.aabox.Extents = XMFLOAT3(0.05f, 0.05f, 0.05f); +} + +void Sample::Animate(double fTime) +{ + float t = static_cast(fTime * 0.2); + + const float camera0OriginX = XMVectorGetX(m_cameraOrigins[0]); + const float camera1OriginX = XMVectorGetX(m_cameraOrigins[1]); + const float camera2OriginX = XMVectorGetX(m_cameraOrigins[2]); + const float camera3OriginX = XMVectorGetX(m_cameraOrigins[3]); + const float camera3OriginZ = XMVectorGetZ(m_cameraOrigins[3]); + + // animate sphere 0 around the frustum + m_secondarySpheres[0].sphere.Center.x = 10.f * sinf(3.f * t); + m_secondarySpheres[0].sphere.Center.y = 7.f * cosf(5.f * t); + + // animate oriented box 0 around the frustum + m_secondaryOrientedBoxes[0].obox.Center.x = 8.f * sinf(3.5f * t); + m_secondaryOrientedBoxes[0].obox.Center.y = 5.f * cosf(5.1f * t); + XMStoreFloat4(&(m_secondaryOrientedBoxes[0].obox.Orientation), XMQuaternionRotationRollPitchYaw(t * 1.4f, t * 0.2f, t)); + + // animate aligned box 0 around the frustum + m_secondaryAABoxes[0].aabox.Center.x = 10.f * sinf(2.1f * t); + m_secondaryAABoxes[0].aabox.Center.y = 7.f * cosf(3.8f * t); + + // animate sphere 1 around the aligned box + m_secondarySpheres[1].sphere.Center.x = 8.f * sinf(2.9f * t) + camera1OriginX; + m_secondarySpheres[1].sphere.Center.y = 8.f * cosf(4.6f * t); + m_secondarySpheres[1].sphere.Center.z = 8.f * cosf(1.6f * t); + + // animate oriented box 1 around the aligned box + m_secondaryOrientedBoxes[1].obox.Center.x = 8.f * sinf(3.2f * t) + camera1OriginX; + m_secondaryOrientedBoxes[1].obox.Center.y = 8.f * cosf(2.1f * t); + m_secondaryOrientedBoxes[1].obox.Center.z = 8.f * sinf(1.6f * t); + XMStoreFloat4(&(m_secondaryOrientedBoxes[1].obox.Orientation), XMQuaternionRotationRollPitchYaw(t * 0.7f, t * 1.3f, t)); + + // animate aligned box 1 around the aligned box + m_secondaryAABoxes[1].aabox.Center.x = 8.f * sinf(1.1f * t) + camera1OriginX; + m_secondaryAABoxes[1].aabox.Center.y = 8.f * cosf(5.8f * t); + m_secondaryAABoxes[1].aabox.Center.z = 8.f * cosf(3.0f * t); + + // animate sphere 2 around the oriented box + m_secondarySpheres[2].sphere.Center.x = 8.f * sinf(2.2f * t) + camera2OriginX; + m_secondarySpheres[2].sphere.Center.y = 8.f * cosf(4.3f * t); + m_secondarySpheres[2].sphere.Center.z = 8.f * cosf(1.8f * t); + + // animate oriented box 2 around the oriented box + m_secondaryOrientedBoxes[2].obox.Center.x = 8.f * sinf(3.7f * t) + camera2OriginX; + m_secondaryOrientedBoxes[2].obox.Center.y = 8.f * cosf(2.5f * t); + m_secondaryOrientedBoxes[2].obox.Center.z = 8.f * sinf(1.1f * t); + XMStoreFloat4(&(m_secondaryOrientedBoxes[2].obox.Orientation), XMQuaternionRotationRollPitchYaw(t * 0.9f, t * 1.8f, t)); + + // animate aligned box 2 around the oriented box + m_secondaryAABoxes[2].aabox.Center.x = 8.f * sinf(1.3f * t) + camera2OriginX; + m_secondaryAABoxes[2].aabox.Center.y = 8.f * cosf(5.2f * t); + m_secondaryAABoxes[2].aabox.Center.z = 8.f * cosf(3.5f * t); + + // triangle points in local space - equilateral triangle with radius of 2 + const static XMVECTORF32 TrianglePointA = { 0.f, 2.f, 0.f, 0.f }; + const static XMVECTORF32 TrianglePointB = { 1.732f, -1.f, 0.f, 0.f }; + const static XMVECTORF32 TrianglePointC = { -1.732f, -1.f, 0.f, 0.f }; + + // animate triangle 0 around the frustum + XMMATRIX TriangleCoords = XMMatrixRotationRollPitchYaw(t * 1.4f, t * 2.5f, t); + XMMATRIX Translation = XMMatrixTranslation(5.f * sinf(5.3f * t) + camera0OriginX, 5.f * cosf(2.3f * t), 5.f * sinf(3.4f * t)); + TriangleCoords = XMMatrixMultiply(TriangleCoords, Translation); + m_secondaryTriangles[0].pointa = XMVector3Transform(TrianglePointA, TriangleCoords); + m_secondaryTriangles[0].pointb = XMVector3Transform(TrianglePointB, TriangleCoords); + m_secondaryTriangles[0].pointc = XMVector3Transform(TrianglePointC, TriangleCoords); + + // animate triangle 1 around the aligned box + TriangleCoords = XMMatrixRotationRollPitchYaw(t * 1.4f, t * 2.5f, t); + Translation = XMMatrixTranslation(8.f * sinf(5.3f * t) + camera1OriginX, 8.f * cosf(2.3f * t), 8.f * sinf(3.4f * t)); + TriangleCoords = XMMatrixMultiply(TriangleCoords, Translation); + m_secondaryTriangles[1].pointa = XMVector3Transform(TrianglePointA, TriangleCoords); + m_secondaryTriangles[1].pointb = XMVector3Transform(TrianglePointB, TriangleCoords); + m_secondaryTriangles[1].pointc = XMVector3Transform(TrianglePointC, TriangleCoords); + + // animate triangle 2 around the oriented box + TriangleCoords = XMMatrixRotationRollPitchYaw(t * 1.4f, t * 2.5f, t); + Translation = XMMatrixTranslation(8.f * sinf(5.3f * t) + camera2OriginX, 8.f * cosf(2.3f * t), 8.f * sinf(3.4f * t)); + TriangleCoords = XMMatrixMultiply(TriangleCoords, Translation); + m_secondaryTriangles[2].pointa = XMVector3Transform(TrianglePointA, TriangleCoords); + m_secondaryTriangles[2].pointb = XMVector3Transform(TrianglePointB, TriangleCoords); + m_secondaryTriangles[2].pointc = XMVector3Transform(TrianglePointC, TriangleCoords); + + // animate primary ray (this is the only animated primary object) + m_primaryRay.direction = Vector3(sinf(t * 3.f), 0.f, cosf(t * 3.f)); + + // animate sphere 3 around the ray + m_secondarySpheres[3].sphere.Center = XMFLOAT3(camera3OriginX - 3.f, 0.5f * sinf(t * 5.f), camera3OriginZ); + + // animate aligned box 3 around the ray + m_secondaryAABoxes[3].aabox.Center = XMFLOAT3(camera3OriginX + 3.f, 0.5f * sinf(t * 4.f), camera3OriginZ); + + // animate oriented box 3 around the ray + m_secondaryOrientedBoxes[3].obox.Center = XMFLOAT3(camera3OriginX, 0.5f * sinf(t * 4.5f), camera3OriginZ + 3.f); + XMStoreFloat4(&(m_secondaryOrientedBoxes[3].obox.Orientation), XMQuaternionRotationRollPitchYaw(t * 0.9f, t * 1.8f, t)); + + // animate triangle 3 around the ray + TriangleCoords = XMMatrixRotationRollPitchYaw(t * 1.4f, t * 2.5f, t); + Translation = XMMatrixTranslation(camera3OriginX, 0.5f * cosf(4.3f * t), camera3OriginZ - 3.f); + TriangleCoords = XMMatrixMultiply(TriangleCoords, Translation); + m_secondaryTriangles[3].pointa = XMVector3Transform(TrianglePointA, TriangleCoords); + m_secondaryTriangles[3].pointb = XMVector3Transform(TrianglePointB, TriangleCoords); + m_secondaryTriangles[3].pointc = XMVector3Transform(TrianglePointC, TriangleCoords); +} + +void Sample::Collide() +{ + // test collisions between objects and frustum + m_secondarySpheres[0].collision = m_primaryFrustum.Contains(m_secondarySpheres[0].sphere); + m_secondaryOrientedBoxes[0].collision = m_primaryFrustum.Contains(m_secondaryOrientedBoxes[0].obox); + m_secondaryAABoxes[0].collision = m_primaryFrustum.Contains(m_secondaryAABoxes[0].aabox); + m_secondaryTriangles[0].collision = m_primaryFrustum.Contains(m_secondaryTriangles[0].pointa, + m_secondaryTriangles[0].pointb, + m_secondaryTriangles[0].pointc); + + // test collisions between objects and aligned box + m_secondarySpheres[1].collision = m_primaryAABox.Contains(m_secondarySpheres[1].sphere); + m_secondaryOrientedBoxes[1].collision = m_primaryAABox.Contains(m_secondaryOrientedBoxes[1].obox); + m_secondaryAABoxes[1].collision = m_primaryAABox.Contains(m_secondaryAABoxes[1].aabox); + m_secondaryTriangles[1].collision = m_primaryAABox.Contains(m_secondaryTriangles[1].pointa, + m_secondaryTriangles[1].pointb, + m_secondaryTriangles[1].pointc); + + // test collisions between objects and oriented box + m_secondarySpheres[2].collision = m_primaryOrientedBox.Contains(m_secondarySpheres[2].sphere); + m_secondaryOrientedBoxes[2].collision = m_primaryOrientedBox.Contains(m_secondaryOrientedBoxes[2].obox); + m_secondaryAABoxes[2].collision = m_primaryOrientedBox.Contains(m_secondaryAABoxes[2].aabox); + m_secondaryTriangles[2].collision = m_primaryOrientedBox.Contains(m_secondaryTriangles[2].pointa, + m_secondaryTriangles[2].pointb, + m_secondaryTriangles[2].pointc); + + // test collisions between objects and ray + float fDistance = -1.0f; + + float fDist; + if (m_secondarySpheres[3].sphere.Intersects(m_primaryRay.origin, m_primaryRay.direction, fDist)) + { + fDistance = fDist; + m_secondarySpheres[3].collision = INTERSECTS; + } + else + m_secondarySpheres[3].collision = DISJOINT; + + if (m_secondaryOrientedBoxes[3].obox.Intersects(m_primaryRay.origin, m_primaryRay.direction, fDist)) + { + fDistance = fDist; + m_secondaryOrientedBoxes[3].collision = INTERSECTS; + } + else + m_secondaryOrientedBoxes[3].collision = DISJOINT; + + if (m_secondaryAABoxes[3].aabox.Intersects(m_primaryRay.origin, m_primaryRay.direction, fDist)) + { + fDistance = fDist; + m_secondaryAABoxes[3].collision = INTERSECTS; + } + else + m_secondaryAABoxes[3].collision = DISJOINT; + + if (TriangleTests::Intersects(m_primaryRay.origin, m_primaryRay.direction, + m_secondaryTriangles[3].pointa, + m_secondaryTriangles[3].pointb, + m_secondaryTriangles[3].pointc, + fDist)) + { + fDistance = fDist; + m_secondaryTriangles[3].collision = INTERSECTS; + } + else + m_secondaryTriangles[3].collision = DISJOINT; + + // If one of the ray intersection tests was successful, fDistance will be positive. + // If so, compute the intersection location and store it in g_RayHitResultBox. + if (fDistance > 0) + { + // The primary ray's direction is assumed to be normalized. + XMVECTOR HitLocation = XMVectorMultiplyAdd(m_primaryRay.direction, XMVectorReplicate(fDistance), + m_primaryRay.origin); + XMStoreFloat3(&m_rayHitResultBox.aabox.Center, HitLocation); + m_rayHitResultBox.collision = INTERSECTS; + } + else + { + m_rayHitResultBox.collision = DISJOINT; + } +} + +//-------------------------------------------------------------------------------------- +// Sets the camera to view a particular group of objects +//-------------------------------------------------------------------------------------- +void Sample::SetViewForGroup(int group) +{ + assert(group < c_groupCount); + + m_camera.SetFocus(m_cameraOrigins[group]); + m_camera.SetRotation(XMQuaternionRotationRollPitchYaw(-XM_PI / 4.f, 0.f, 0.f)); + + switch (group) + { + default: m_name = L"Frustum"; break; + case 1: m_name = L"Axis-aligned box"; break; + case 2: m_name = L"Oriented box"; break; + case 3: m_name = L"Ray"; break; + } +} + diff --git a/XDKSamples/System/Collision/Collision.h b/XDKSamples/System/Collision/Collision.h new file mode 100644 index 0000000000000000000000000000000000000000..e86ce1c84c5fff96ec865de7b500359e58b2713f --- /dev/null +++ b/XDKSamples/System/Collision/Collision.h @@ -0,0 +1,141 @@ +//-------------------------------------------------------------------------------------- +// Collision.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "ControllerHelp.h" +#include "OrbitCamera.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void InitializeObjects(); + void Animate(double fTime); + void Collide(); + void SetViewForGroup(int group); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // Rendering objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_states; + std::unique_ptr m_effect; + std::unique_ptr> m_batch; + std::unique_ptr m_font; + std::unique_ptr m_sprites; + + Microsoft::WRL::ComPtr m_layout; + + std::wstring m_name; + + // Sample Help. + std::unique_ptr m_help; + bool m_showHelp; + + // View camera. + DX::OrbitCamera m_camera; + + // Collision sample. + using BoundingSphere = DirectX::BoundingSphere; + using BoundingOrientedBox = DirectX::BoundingOrientedBox; + using BoundingBox = DirectX::BoundingBox; + using BoundingFrustum = DirectX::BoundingFrustum; + using ContainmentType = DirectX::ContainmentType; + using Vector3 = DirectX::SimpleMath::Vector3; + + struct CollisionSphere + { + BoundingSphere sphere; + ContainmentType collision; + }; + + struct CollisionBox + { + BoundingOrientedBox obox; + ContainmentType collision; + }; + + struct CollisionAABox + { + BoundingBox aabox; + ContainmentType collision; + }; + + struct CollisionFrustum + { + BoundingFrustum frustum; + ContainmentType collision; + }; + + struct CollisionTriangle + { + Vector3 pointa; + Vector3 pointb; + Vector3 pointc; + ContainmentType collision; + }; + + struct CollisionRay + { + Vector3 origin; + Vector3 direction; + }; + + static const size_t c_groupCount = 4; + + BoundingFrustum m_primaryFrustum; + BoundingOrientedBox m_primaryOrientedBox; + BoundingBox m_primaryAABox; + CollisionRay m_primaryRay; + + CollisionSphere m_secondarySpheres[c_groupCount]; + CollisionBox m_secondaryOrientedBoxes[c_groupCount]; + CollisionAABox m_secondaryAABoxes[c_groupCount]; + CollisionTriangle m_secondaryTriangles[c_groupCount]; + + CollisionAABox m_rayHitResultBox; + + Vector3 m_cameraOrigins[c_groupCount]; +}; diff --git a/XDKSamples/System/Collision/Collision.sln b/XDKSamples/System/Collision/Collision.sln new file mode 100644 index 0000000000000000000000000000000000000000..e35e249627ef05bacd5bd1e0d3f23f5a003987ca --- /dev/null +++ b/XDKSamples/System/Collision/Collision.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Collision", "Collision.vcxproj", "{ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Debug|Durango.ActiveCfg = Debug|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Debug|Durango.Build.0 = Debug|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Debug|Durango.Deploy.0 = Debug|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Profile|Durango.ActiveCfg = Profile|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Profile|Durango.Build.0 = Profile|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Profile|Durango.Deploy.0 = Profile|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Release|Durango.ActiveCfg = Release|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Release|Durango.Build.0 = Release|Durango + {ECBAC69D-44F7-4C0C-A5B7-EF45CA20C999}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/Collision/Collision.vcxproj b/XDKSamples/System/Collision/Collision.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6726b7b19847fe66afcb0304aba12a92a1e8e74f --- /dev/null +++ b/XDKSamples/System/Collision/Collision.vcxproj @@ -0,0 +1,232 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + Collision + {ecbac69d-44f7-4c0c-a5b7-ef45ca20c999} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/Collision/Collision.vcxproj.filters b/XDKSamples/System/Collision/Collision.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..eea712af7e5c7bfd1647293520f36dfb78632d0f --- /dev/null +++ b/XDKSamples/System/Collision/Collision.vcxproj.filters @@ -0,0 +1,98 @@ + + + + + 9d5e500f-093c-4b32-9ce4-f9810545351f + + + 30290ae1-46e4-4844-9ac4-83fa3df83e01 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {4ea9818a-3beb-42ed-87af-906feafcf6c2} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/Collision/DeviceResources.cpp b/XDKSamples/System/Collision/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/System/Collision/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/Collision/DeviceResources.h b/XDKSamples/System/Collision/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/System/Collision/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/Collision/Main.cpp b/XDKSamples/System/Collision/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3bdb26f7410bc0ba135301a8c19648b51bd39ee --- /dev/null +++ b/XDKSamples/System/Collision/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Collision.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/Collision/Package.appxmanifest b/XDKSamples/System/Collision/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..051ca40f775fd4cd971ad0431781a10c55145a2d --- /dev/null +++ b/XDKSamples/System/Collision/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + Collision + Xbox Advanced Technology Group + Assets\StoreLogo.png + Collision + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/Collision/Readme.docx b/XDKSamples/System/Collision/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..de2a813a32f29ef5694f563e14c4c5e30440b71c Binary files /dev/null and b/XDKSamples/System/Collision/Readme.docx differ diff --git a/XDKSamples/System/Collision/StepTimer.h b/XDKSamples/System/Collision/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/Collision/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/Collision/Telemetry.h b/XDKSamples/System/Collision/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/Collision/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/Collision/pch.cpp b/XDKSamples/System/Collision/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/Collision/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/Collision/pch.h b/XDKSamples/System/Collision/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..b770d291f16b72ab327fec66361dcd14478b04d5 --- /dev/null +++ b/XDKSamples/System/Collision/pch.h @@ -0,0 +1,74 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +// Include the DirectXMath collision types +#include + +#include +#include +#include +#include + +#include +#include + +#include "CommonStates.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "PrimitiveBatch.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "VertexTypes.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/DataBreakpoints/Assets/Logo.png b/XDKSamples/System/DataBreakpoints/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/DataBreakpoints/Assets/Logo.png differ diff --git a/XDKSamples/System/DataBreakpoints/Assets/SmallLogo.png b/XDKSamples/System/DataBreakpoints/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/DataBreakpoints/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/DataBreakpoints/Assets/SplashScreen.png b/XDKSamples/System/DataBreakpoints/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/DataBreakpoints/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/DataBreakpoints/Assets/StoreLogo.png b/XDKSamples/System/DataBreakpoints/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/DataBreakpoints/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/DataBreakpoints/Assets/WideLogo.png b/XDKSamples/System/DataBreakpoints/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/DataBreakpoints/Assets/WideLogo.png differ diff --git a/XDKSamples/System/DataBreakpoints/DataBreak.cpp b/XDKSamples/System/DataBreakpoints/DataBreak.cpp new file mode 100644 index 0000000000000000000000000000000000000000..823b712d84cc5d33aa9424ebb1daa9eb499c1fbc --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreak.cpp @@ -0,0 +1,219 @@ +//-------------------------------------------------------------------------------------- +// DataBreak.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DataBreak.h" +#include +#include "windows.h" + +namespace ATG +{ + namespace DataBreak + { + struct DataBreakThreadParams + { + HANDLE threadHandle; // Which thread to set the breakpoint on + uintptr_t address; // The location in memory for the breakpoint + DEBUG_REGISTER debugRegister; // Which of the four register slots to modify + ADDRESS_SIZE addressSize; // How many bytes for the range used by the breakpoint + ADDRESS_OPERATION addressOperation; // Should this be an execution, read/write, or write breakpoint + bool addDebugUsage; // Add the breakpoint or clear the breakpoint + bool success; // Was the operation successful + }; + + // The debug registers can only be accessed from Ring 0 which not available to user mode code + // The trick is to get the kernel to modify the registers for user mode code. + // This is done through modifying the thread context. The context can only be modified when the thread is suspended + // This sample creates a unique thread to perform the modification and DataBreakThread is the thread function + void DataBreakThread(DataBreakThreadParams& params) + { + CONTEXT threadContext; + threadContext.ContextFlags = CONTEXT_DEBUG_REGISTERS; // We're only interested in the debug registers + params.success = false; + if (SuspendThread(params.threadHandle) == ((DWORD)-1)) // The thread must be suspended to query its context without getting bogus data + return; + + if (GetThreadContext(params.threadHandle, &threadContext) == 0) + { + ResumeThread(params.threadHandle); + return; + } + + // debug registers 0,1,2,3 hold the address for slot 1,2,3,4 + // debug register 7 contains the control data for how to interpret each slot + + if (!params.addDebugUsage) // Clearing the debug register slot + { + switch (params.debugRegister) // This code uses local breakpoints which are bits 0,2,4,6 for slot 1,2,3,4 + { // On a task switch these flags are swapped with the value from the new task + case DEBUG_REGISTER::REGISTER_1: // Bits 1,3,5,7 represent global breakpoint mode. This enables breakpoints for all tasks + threadContext.Dr7 &= ~(1 << 0); // However Windows sanitizes these flags when setting the thread context and clears the global bits + threadContext.Dr0 = 0; + break; + case DEBUG_REGISTER::REGISTER_2: + threadContext.Dr7 &= ~(1 << 2); + threadContext.Dr1 = 0; + break; + case DEBUG_REGISTER::REGISTER_3: + threadContext.Dr7 &= ~(1 << 4); + threadContext.Dr2 = 0; + break; + case DEBUG_REGISTER::REGISTER_4: + threadContext.Dr7 &= ~(1 << 6); + threadContext.Dr3 = 0; + break; + } + } + else + { + if (params.addressOperation == ADDRESS_OPERATION::EXECUTION) // all execution breakpoints require length 1 for later flags + params.addressSize = ADDRESS_SIZE::SIZE_1; + + switch (params.addressSize) // The address for a breakpoint needs to be aligned to the requested size + { + case ADDRESS_SIZE::SIZE_2: + params.address &= ~0x01; + break; + case ADDRESS_SIZE::SIZE_4: + params.address &= ~0x03; + break; + case ADDRESS_SIZE::SIZE_8: + params.address &= ~0x07; + break; + } + + threadContext.Dr6 = 0; // debug register 6 represents the status when an exception is fired. These flags should be cleared in this case + threadContext.Dr7 |= (1 << 8); // Bits 8 tells the processor to report the exact instruction that triggered the breakpoint for local breakpoints + uint32_t registerIndex = 0; + switch (params.debugRegister) // This code uses local breakpoints which are bits 0,2,4,6 for slot 1,2,3,4 + { // On a task switch these flags are swapped with the value from the new task + case DEBUG_REGISTER::REGISTER_1: // Bits 1,3,5,7 represent global breakpoint mode. This enables breakpoints for all tasks + threadContext.Dr7 |= (1 << 0); // However Windows sanitizes these flags when setting the thread context and clears the global bits + threadContext.Dr0 = (DWORD64)params.address; + registerIndex = 0; + break; + case DEBUG_REGISTER::REGISTER_2: + threadContext.Dr7 |= (1 << 2); + threadContext.Dr1 = (DWORD64)params.address; + registerIndex = 1; + break; + case DEBUG_REGISTER::REGISTER_3: + threadContext.Dr7 |= (1 << 4); + threadContext.Dr2 = (DWORD64)params.address; + registerIndex = 2; + break; + case DEBUG_REGISTER::REGISTER_4: + threadContext.Dr7 |= (1 << 6); + threadContext.Dr3 = (DWORD64)params.address; + registerIndex = 3; + break; + } + + threadContext.Dr7 &= ~((3 << 18) << (registerIndex * 4)); // Bits 18-19, 22-23, 26-27, 30-31 represent the address length for slot 1,2,3,4 + switch (params.addressSize) + { + case ADDRESS_SIZE::SIZE_1: + threadContext.Dr7 |= ((0 << 18) << (registerIndex * 4)); + break; + case ADDRESS_SIZE::SIZE_2: + threadContext.Dr7 |= ((1 << 18) << (registerIndex * 4)); + break; + case ADDRESS_SIZE::SIZE_4: + threadContext.Dr7 |= ((3 << 18) << (registerIndex * 4)); + break; + case ADDRESS_SIZE::SIZE_8: + threadContext.Dr7 |= ((2 << 18) << (registerIndex * 4)); + break; + } + threadContext.Dr7 &= ~((3 << 16) << (registerIndex * 4)); // Bits 16-17, 20-21, 24-25, 28-29 represent the type of breakpoint for slot 1,2,3,4 + switch (params.addressOperation) + { + case ADDRESS_OPERATION::EXECUTION: + threadContext.Dr7 |= ((0 << 16) << (registerIndex * 4)); + break; + case ADDRESS_OPERATION::WRITE: + threadContext.Dr7 |= ((1 << 16) << (registerIndex * 4)); + break; + case ADDRESS_OPERATION::READ_WRITE: + threadContext.Dr7 |= ((3 << 16) << (registerIndex * 4)); + break; + } + } + + // only if we were able to set the new thread context then it was a success + if (SetThreadContext(params.threadHandle, &threadContext) != 0) + params.success = true; + ResumeThread(params.threadHandle); + } + + //************************************ + // Method: SetHardwareBreakPointForThread + // FullName: ATG::DataBreak::SetHardwareBreakPointForThread + // Returns: bool indicating success or failure + // Parameter: void * thread Which thread to set the breakpoint for, can be the current thread, Windows HANDLE object + // Parameter: void * address The location in memory of the breakpoint + // Parameter: DEBUG_REGISTER debugRegister Which debug register slot to use on the processor, only 4 hardware breakpoints are supported + // Parameter: ADDRESS_OPERATION addressOperation What type of operation to break on + // Parameter: ADDRESS_SIZE addressSize How big is the memory location in questions, 1 byte, 2 bytes, etc. + //************************************ + bool SetHardwareBreakPointForThread(HANDLE thread, void *address, DEBUG_REGISTER debugRegister, ADDRESS_OPERATION addressOperation, ADDRESS_SIZE addressSize) + { + DataBreakThreadParams params; + params.threadHandle = thread; + params.address = reinterpret_cast (address); + params.addDebugUsage = true; + params.debugRegister = debugRegister; + params.addressSize = addressSize; + params.addressOperation = addressOperation; + params.success = false; + if (GetCurrentThreadId() == GetThreadId(thread)) // Setting the breakpoint for the current thread requires another thread to perform the action + { + std::thread *dataBreakThread; + + dataBreakThread = new std::thread(DataBreakThread, params); + dataBreakThread->join(); + } + else + { + DataBreakThread(params); + } + return params.success; + } + + //************************************ + // Method: ClearHardwareBreakPointForThread + // FullName: ATG::DataBreak::ClearHardwareBreakPointForThread + // Returns: bool indicating success or failure + // Parameter: void * thread Which thread to clear the breakpoint for, can be the current thread + // Parameter: DEBUG_REGISTER debugRegister Which debug register to use on the processor, only 4 hardware breakpoints are supported + //************************************ + bool ClearHardwareBreakPointForThread(HANDLE thread, DEBUG_REGISTER debugRegister) + { + DataBreakThreadParams params; + + params.threadHandle = thread; + params.address = 0; + params.addDebugUsage = false; + params.debugRegister = debugRegister; + params.addressSize = ADDRESS_SIZE::SIZE_1; + params.addressOperation = ADDRESS_OPERATION::READ_WRITE; + params.success = false; + if (GetCurrentThreadId() == GetThreadId(thread)) // clearing the breakpoint for the current thread requires another thread to perform the action + { + std::thread *dataBreakThread; + + dataBreakThread = new std::thread(DataBreakThread, params); + dataBreakThread->join(); + } + else + { + DataBreakThread(params); + } + return params.success; + } + } +} diff --git a/XDKSamples/System/DataBreakpoints/DataBreak.h b/XDKSamples/System/DataBreakpoints/DataBreak.h new file mode 100644 index 0000000000000000000000000000000000000000..cc8ca897f97227c0b4e5bfce00f51bda6f60ac10 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreak.h @@ -0,0 +1,57 @@ +//-------------------------------------------------------------------------------------- +// DataBreak.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +namespace ATG +{ + namespace DataBreak + { + enum class ADDRESS_SIZE { + SIZE_1, // 1 byte + SIZE_2, // 2 bytes + SIZE_4, // 4 bytes + SIZE_8 // 8 bytes + }; + enum class ADDRESS_OPERATION + { + EXECUTION, // A specific address was accessed for execution. This only applies to the first byte of a full instruction + READ_WRITE, // An address was either read from or written to + WRITE, // An address was written to + }; + + enum class DEBUG_REGISTER // There are only four slots available for hardware breakpoints + { + REGISTER_1, + REGISTER_2, + REGISTER_3, + REGISTER_4, + }; + + //************************************ + // Method: SetHardwareBreakPointForThread + // FullName: ATG::DataBreak::SetHardwareBreakPointForThread + // Returns: bool indicating success or failure + // Parameter: void * thread Which thread to set the breakpoint for, can be the current thread, Windows HANDLE object + // Parameter: void * address The location in memory of the breakpoint + // Parameter: DEBUG_REGISTER debugRegister Which debug register slot to use on the processor, only 4 hardware breakpoints are supported + // Parameter: ADDRESS_OPERATION addressOperation What type of operation to break on + // Parameter: ADDRESS_SIZE addressSize How big is the memory location in questions, 1 byte, 2 bytes, etc. + //************************************ + bool SetHardwareBreakPointForThread(void *thread, void *address, DEBUG_REGISTER debugRegister, ADDRESS_OPERATION addressOperation, ADDRESS_SIZE addressSize); + + //************************************ + // Method: ClearHardwareBreakPointForThread + // FullName: ATG::DataBreak::ClearHardwareBreakPointForThread + // Returns: bool indicating success or failure + // Parameter: void * thread Which thread to clear the breakpoint for, can be the current thread + // Parameter: DEBUG_REGISTER debugRegister Which debug register to use on the processor, only 4 hardware breakpoints are supported + //************************************ + bool ClearHardwareBreakPointForThread(void *thread, DEBUG_REGISTER debugRegister); + } +} diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpoint.cpp b/XDKSamples/System/DataBreakpoints/DataBreakpoint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e599c4815122749b8d62611bb4ecbce2d08f91c --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpoint.cpp @@ -0,0 +1,272 @@ +//-------------------------------------------------------------------------------------- +// DataBreakpoint.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DataBreakpoint.h" +#include "ControllerFont.h" + +#include "ATGColors.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0) + , m_executionTestResult(TestStatus::TEST_NOT_RUN) + , m_readTestResult(TestStatus::TEST_NOT_RUN) + , m_readWriteTestResult(TestStatus::TEST_NOT_RUN) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& /*timer*/) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (m_gamePadButtons.a == DirectX::GamePad::ButtonStateTracker::PRESSED) + { + m_executionTestResult = m_dataTest.RunTest(DataBreakpointTest::WhichTest::ExecutionTest) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (m_gamePadButtons.b == DirectX::GamePad::ButtonStateTracker::PRESSED) + { + m_readTestResult = m_dataTest.RunTest(DataBreakpointTest::WhichTest::ReadTest) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (m_gamePadButtons.x == DirectX::GamePad::ButtonStateTracker::PRESSED) + { + m_readWriteTestResult = m_dataTest.RunTest(DataBreakpointTest::WhichTest::ReadWriteTest) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(1920, 1080); + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + std::wstring outputString; + outputString = L"Data Breakpoint Tests "; + uint32_t numDots = (m_timer.GetFrameCount() % 10) + 1; + for (uint32_t i = 0; i < numDots; i++) + { + outputString += L"."; + } + m_font->DrawString(m_spriteBatch.get(), outputString.c_str(), pos); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[A]", L"Execution Breakpoint", m_executionTestResult, pos); + DrawHelpText(pos, DataBreakpointTest::WhichTest::ExecutionTest); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[B]", L"Read Breakpoint", m_readTestResult, pos); + DrawHelpText(pos, DataBreakpointTest::WhichTest::ReadTest); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[X]", L"Read/Write Breakpoint", m_readWriteTestResult, pos); + DrawHelpText(pos, DataBreakpointTest::WhichTest::ReadWriteTest); + pos.y += m_font->GetLineSpacing() * 3; + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +void Sample::DrawStatusString(const std::wstring& button, const std::wstring& testName, TestStatus status, XMFLOAT2& pos) +{ + RECT stringBounds; + std::wstring outputString; + std::wstring resultString; + XMVECTORF32 resultColor = ATG::Colors::OffWhite; + outputString = L"Press "; + outputString += button; + outputString += L" to run "; + outputString += testName; + outputString += L" Test: "; + switch (status) + { + case TestStatus::TEST_NOT_RUN: + resultString += L"not run yet"; + break; + case TestStatus::TEST_SUCCESS: + resultString += L"success"; + resultColor = ATG::Colors::Green; + break; + case TestStatus::TEST_FAILURE: + resultString += L"failure"; + resultColor = ATG::Colors::Orange; + break; + } + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), outputString.c_str(), pos); + stringBounds = DX::MeasureControllerDrawBounds(m_font.get(), m_ctrlFont.get(), outputString.c_str(), pos); + pos.x += (stringBounds.right - stringBounds.left); + m_font->DrawString(m_spriteBatch.get(), resultString.c_str(), pos, resultColor); + pos.x -= (stringBounds.right - stringBounds.left); +} + +void Sample::DrawHelpText(DirectX::XMFLOAT2& pos, DataBreakpointTest::WhichTest whichTest) +{ + static const wchar_t *helpText[] = { + L" Execution breakpoints.", + L" Sets a breakpoint when a particular instruction is executed, for example the entry point of a function.", + L" This is useful in finding specific code paths during automation, for instance calling physics outside the physics phase", + L" Memory read breakpoints.", + L" Sets a breakpoint when a particular variable is read from.", + L" This is useful to track down issues where data is being used after delete if the breakpoint is set during free.", + L" Memory read/write breakpoints", + L" Sets a breakpoint when a particular memory address is either written to or read from.", + L" This is useful to track down various memory issues like access off the end of an array. Set a breakpoint at the first address past the array.", + }; + uint32_t startIndex(0); + switch (whichTest) + { + case DataBreakpointTest::WhichTest::ExecutionTest: + startIndex = 0; + break; + case DataBreakpointTest::WhichTest::ReadTest: + startIndex = 3; + break; + case DataBreakpointTest::WhichTest::ReadWriteTest: + startIndex = 6; + break; + } + for (uint32_t i = 0; i < 3; i++) + { + pos.y += m_font->GetLineSpacing() * 1.1f; + m_font->DrawString(m_spriteBatch.get(), helpText[i + startIndex], pos); + } +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneController.spritefont"); + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpoint.h b/XDKSamples/System/DataBreakpoints/DataBreakpoint.h new file mode 100644 index 0000000000000000000000000000000000000000..2d5c578bf42e88f9eb94c4c6ce4ac78ec5abfcd5 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpoint.h @@ -0,0 +1,74 @@ +//-------------------------------------------------------------------------------------- +// DataBreakpoint.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "DataBreakpointTest.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // Sample specific objects + enum class TestStatus + { + TEST_NOT_RUN, + TEST_SUCCESS, + TEST_FAILURE, + }; + DataBreakpointTest m_dataTest; + TestStatus m_executionTestResult; + TestStatus m_readTestResult; + TestStatus m_readWriteTestResult; + + void DrawStatusString(const std::wstring& button, const std::wstring& testName, TestStatus status, DirectX::XMFLOAT2& pos); + void DrawHelpText(DirectX::XMFLOAT2& pos, DataBreakpointTest::WhichTest); + + // DirectXTK objects. + Microsoft::WRL::ComPtr m_background; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; +}; diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpoint.vcxproj b/XDKSamples/System/DataBreakpoints/DataBreakpoint.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..93341ea0494f5e76a8194919b59fbae5e7672733 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpoint.vcxproj @@ -0,0 +1,228 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + DataBreakpoint + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + toolhelpx.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\CPUTK;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + true + false + + + 5.0 + + + + + toolhelpx.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\CPUTK;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + true + + + 5.0 + + + + + toolhelpx.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\CPUTK;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + true + + + 5.0 + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + Designer + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + + + true + true + true + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpoint.vcxproj.filters b/XDKSamples/System/DataBreakpoints/DataBreakpoint.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..c17cb7bc79c7680795fbe9dc4687c30cfd8b62cf --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpoint.vcxproj.filters @@ -0,0 +1,84 @@ + + + + + 2af962bd-f696-4946-9198-f449203e6a7c + + + dcb95d67-37be-4e59-adff-4f59ae054849 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {9818b763-1ba3-4b61-99b4-098728d35f3d} + + + {7072370a-7c71-4a79-b7d3-a09bf4b1529e} + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + CPU Took Kit + + + + + + ATG Tool Kit + + + + + + + Common + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpointSystem.sln b/XDKSamples/System/DataBreakpoints/DataBreakpointSystem.sln new file mode 100644 index 0000000000000000000000000000000000000000..8426f36dcb67da7acd2c713a60090b6abe5459cd --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpointSystem.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DataBreakpoint", "DataBreakpoint.vcxproj", "{B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Debug|Durango.ActiveCfg = Debug|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Debug|Durango.Build.0 = Debug|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Debug|Durango.Deploy.0 = Debug|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Profile|Durango.ActiveCfg = Profile|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Profile|Durango.Build.0 = Profile|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Profile|Durango.Deploy.0 = Profile|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Release|Durango.ActiveCfg = Release|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Release|Durango.Build.0 = Release|Durango + {B2EC4E8F-8A30-4FFD-849C-4D54F9DA4C14}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpointTest.cpp b/XDKSamples/System/DataBreakpoints/DataBreakpointTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54d7dae7527caadd424ac82aa72b738223b066af --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpointTest.cpp @@ -0,0 +1,134 @@ +//-------------------------------------------------------------------------------------- +// DataBreakpointTest.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DataBreakpointTest.h" +#include "DataBreak.h" +#include "algorithm" +#include "dbghelp.h" +#include + +DataBreakpointTest::DataBreakpointTest() : + m_testSuccessful(false) + , m_testThread(nullptr) + , m_shutdownThread(false) +{ +} + +// Test function for the execution breakpoint. This function cannot be inlined otherwise there would be no entry point to use as the address +__declspec (noinline) uint32_t ExecuteTestFunction() +{ + uint32_t temporaryVariableToForceCode; + temporaryVariableToForceCode = 6; + return temporaryVariableToForceCode; +} + +LONG WINAPI GenerateDump(EXCEPTION_POINTERS* pExceptionPointers) +{ + static ATG::CriticalSectionLockable mutex(100); + + std::lock_guard mutexGuard(mutex); // MiniDumpWriteDump is single threaded, must synchronize concurrent calls + + BOOL bMiniDumpSuccessful; + HANDLE hDumpFile; + MINIDUMP_EXCEPTION_INFORMATION ExpParam; + + std::string fileName("t:\\dataBreak.dmp"); + + hDumpFile = CreateFileA(fileName.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); + + ExpParam.ThreadId = GetCurrentThreadId(); + ExpParam.ExceptionPointers = pExceptionPointers; + ExpParam.ClientPointers = TRUE; + + // MiniDumpWriteDump will not actually use the exception pointers record for a single step exception + // It will include the stack all the way down to GetThreadContext during the call to MiniDumpWriteDump + // You will find the offending code in the call stack, but it will be further up. + // Both SEH and the unhandled exception filter are called in the context of the thread with exception. + bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &ExpParam, NULL, NULL); + + CloseHandle(hDumpFile); + + return EXCEPTION_EXECUTE_HANDLER; +} + +uint32_t DataBreakpointTest::TestThreadFunction() +{ + std::atomic tempVariable(0); + for (;;) + { + m_startTestEvent.wait(); + if (m_shutdownThread) + return tempVariable; + + m_testSuccessful = false; + __try + { + switch (m_currentTest) + { + case WhichTest::ExecutionTest: + tempVariable = ExecuteTestFunction(); + break; + case WhichTest::ReadTest: + m_writeFailVariable = 5; + break; + case WhichTest::ReadWriteTest: + tempVariable = m_readWriteFailVariable; + break; + } + } + __except (GenerateDump(GetExceptionInformation())) + { + m_testSuccessful = true; + } + m_testDoneEvent.signal(); + } +} + +bool DataBreakpointTest::RunTest(WhichTest test) +{ + if (m_testThread == nullptr) + { + m_testThread = new std::thread(&DataBreakpointTest::TestThreadFunction, this); + + // setup a read/write breakpoint in slot 1 on m_readWriteFailVariable on the test thread + SetHardwareBreakPointForThread(m_testThread->native_handle(), &m_readWriteFailVariable, ATG::DataBreak::DEBUG_REGISTER::REGISTER_1, ATG::DataBreak::ADDRESS_OPERATION::READ_WRITE, ATG::DataBreak::ADDRESS_SIZE::SIZE_4); + + // setup a write breakpoint in slot 2 on m_writeFailVariable on the test thread, reading will not trigger the breakpoint + SetHardwareBreakPointForThread(m_testThread->native_handle(), &m_writeFailVariable, ATG::DataBreak::DEBUG_REGISTER::REGISTER_2, ATG::DataBreak::ADDRESS_OPERATION::WRITE, ATG::DataBreak::ADDRESS_SIZE::SIZE_4); + + // setup an execution breakpoint for when ExecuteTestFunction was called, however the real function entry point is needed + unsigned char *funcEntry = reinterpret_cast (ExecuteTestFunction); + + // incremental linking works through a jump table. The caller calls to an address that just has a jump instruction to the real function entry point + // we need to detect this and correct the address to find the real function entry for this sample +#ifdef _DEBUG // going to assume incremental linking is enabled for this sample only in debug builds + if (*funcEntry == 0xe9) // a good chance this is the jmp instruction for the jump table + { + uint32_t *offset = reinterpret_cast (funcEntry + 1); + funcEntry += *offset; // this is a relative jump and not an absolute one + funcEntry += 5; // however it's relative to the address after the jump instruction which is 5 bytes long + } + else + { + assert(false); // wasn't what we expected for the jump table and the sample, it's safe to continue past this, the breakpoint for execution may or may not work. + } +#else // This sample has incremental linking disabled for release builds so there should not be a jump table + assert(*funcEntry != 0xe9); +#endif + SetHardwareBreakPointForThread(m_testThread->native_handle(), reinterpret_cast (funcEntry), ATG::DataBreak::DEBUG_REGISTER::REGISTER_3, ATG::DataBreak::ADDRESS_OPERATION::EXECUTION, ATG::DataBreak::ADDRESS_SIZE::SIZE_4); + } + OutputDebugStringW(L"Did a test"); + + m_currentTest = test; + m_testSuccessful = false; + + m_startTestEvent.signal(); // start the test and wait for it to complete + m_testDoneEvent.wait(); + return m_testSuccessful; +} diff --git a/XDKSamples/System/DataBreakpoints/DataBreakpointTest.h b/XDKSamples/System/DataBreakpoints/DataBreakpointTest.h new file mode 100644 index 0000000000000000000000000000000000000000..026270f5a13dec679a8a65dd5cebc94a51aa474a --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DataBreakpointTest.h @@ -0,0 +1,48 @@ +//-------------------------------------------------------------------------------------- +// DataBreakpointTest.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include +#include +#include + +#include "OSLockable.h" + +class DataBreakpointTest +{ +public: + enum class WhichTest + { + ExecutionTest, + ReadTest, + ReadWriteTest + }; +private: + + ATG::EventLockable m_startTestEvent; // used to signal a test should start on the test thread + ATG::EventLockable m_testDoneEvent; // used to notify the main thread the test was completed + std::atomic m_testSuccessful; // was the last test run successful + std::atomic m_shutdownThread; // used to tell the test thread to exit, m_startTestEvent needs to be signalled as well + std::thread *m_testThread; + WhichTest m_currentTest; + + uint32_t m_readWriteFailVariable; // testing variables + uint32_t m_writeFailVariable; + + uint32_t TestThreadFunction(); + +public: + DataBreakpointTest(); + DataBreakpointTest(const DataBreakpointTest& rhs) = delete; + DataBreakpointTest(const DataBreakpointTest&& rhs) = delete; + DataBreakpointTest& operator=(const DataBreakpointTest& rhs) = delete; + + bool RunTest(WhichTest test); +}; diff --git a/XDKSamples/System/DataBreakpoints/DeviceResources.cpp b/XDKSamples/System/DataBreakpoints/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..051840a6dab4898c0c5aed915a810f0ac27ad297 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DeviceResources.cpp @@ -0,0 +1,237 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, bool fastSemantics) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_fastSemantics(fastSemantics) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_fastSemantics) + { + creationFlags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_fastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if (m_fastSemantics && decompressFlags) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/DataBreakpoints/DeviceResources.h b/XDKSamples/System/DataBreakpoints/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..a74ce25c71af7f6b9a766ec071b419b131d991e9 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/DeviceResources.h @@ -0,0 +1,66 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + bool fastSemantics = false); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + bool m_fastSemantics; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/DataBreakpoints/Main.cpp b/XDKSamples/System/DataBreakpoints/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3441e5af0f774d0b59390d21b801975e2273ea60 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/Main.cpp @@ -0,0 +1,144 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DataBreakpoint.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH + 1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/DataBreakpoints/Package.appxmanifest b/XDKSamples/System/DataBreakpoints/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..a9d348b26caee46738037d0d028baff338d6955a --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + DataBreakpoint + Xbox Advanced Technology Group + Assets\StoreLogo.png + DataBreakpoint + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/DataBreakpoints/Readme.docx b/XDKSamples/System/DataBreakpoints/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..4cf28b4b03d1002768efd9ee8419757deab7bcf6 Binary files /dev/null and b/XDKSamples/System/DataBreakpoints/Readme.docx differ diff --git a/XDKSamples/System/DataBreakpoints/StepTimer.h b/XDKSamples/System/DataBreakpoints/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/DataBreakpoints/Telemetry.h b/XDKSamples/System/DataBreakpoints/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/DataBreakpoints/pch.cpp b/XDKSamples/System/DataBreakpoints/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/DataBreakpoints/pch.h b/XDKSamples/System/DataBreakpoints/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..a1a6158b6d0b9ec20916f8256c45da88b90ce97b --- /dev/null +++ b/XDKSamples/System/DataBreakpoints/pch.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "SimpleMath.h" +#include "DDSTextureLoader.h" + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} diff --git a/XDKSamples/System/FlightStick/Assets/Logo.png b/XDKSamples/System/FlightStick/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/FlightStick/Assets/Logo.png differ diff --git a/XDKSamples/System/FlightStick/Assets/SmallLogo.png b/XDKSamples/System/FlightStick/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/FlightStick/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/FlightStick/Assets/SplashScreen.png b/XDKSamples/System/FlightStick/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/FlightStick/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/FlightStick/Assets/StoreLogo.png b/XDKSamples/System/FlightStick/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/FlightStick/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/FlightStick/Assets/WideLogo.png b/XDKSamples/System/FlightStick/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/FlightStick/Assets/WideLogo.png differ diff --git a/XDKSamples/System/FlightStick/DeviceResources.cpp b/XDKSamples/System/FlightStick/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29759abd16cd8674d19a6bdb3f66507f0e0990ea --- /dev/null +++ b/XDKSamples/System/FlightStick/DeviceResources.cpp @@ -0,0 +1,325 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_renderTarget->SetName(L"Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + } + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + + if (m_d3dGameDVRRenderTarget) + { + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + } + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/FlightStick/DeviceResources.h b/XDKSamples/System/FlightStick/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..1edd14523e9006c77bca692edc98d8732d1b0e67 --- /dev/null +++ b/XDKSamples/System/FlightStick/DeviceResources.h @@ -0,0 +1,84 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + static const unsigned int c_EnableHDR = 0x4; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/FlightStick/FlightStick.cpp b/XDKSamples/System/FlightStick/FlightStick.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb71cab2085741e15008dfda1394ecc08f292993 --- /dev/null +++ b/XDKSamples/System/FlightStick/FlightStick.cpp @@ -0,0 +1,345 @@ +//-------------------------------------------------------------------------------------- +// FlightStick.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FlightStick.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; +using namespace Windows::Foundation; +using namespace Microsoft::Xbox::Input; +using namespace Windows::Xbox::Input; + +namespace FlightStickManager +{ + IFlightStick^ GetFirstFlightStick() + { + auto allControllers = Controller::Controllers; + for (unsigned int index = 0; index < allControllers->Size; index++) + { + IController^ currentController = allControllers->GetAt(index); + + if (currentController->Type == L"Microsoft.Xbox.Input.FlightStick") + { + return dynamic_cast(currentController); + } + } + + return nullptr; + } +}; + +Sample::Sample() : + m_extraButtonCount(0), + m_extraAxisCount(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_currentFlightStick = FlightStickManager::GetFirstFlightStick(); + + // Call GetProperties() must be successful to get access to the number of 'extra' buttons/axes/leds; behind the + // scenes we query for device capabilities which can take some time. + // Under the covers, device capabilities will always be queried and 'extra' buttons/axes will be added to the + // report, even without calling GetProperties() + // GetProperties() will wait up to X millseconds before returning. If device capabilities have already been fetched, + // will return immediately. + // If you don't care about the number of 'extra' buttons/axes/leds, GetProperties() never needs to be called. + if (m_currentFlightStick != nullptr) + { + m_currentFlightStickProperties = nullptr; + while (m_currentFlightStickProperties == nullptr) + { + // Once the properties are retrieved, they will never change (for a particular FlightStick), so only + // need to be retrieved once. + m_currentFlightStickProperties = m_currentFlightStick->GetProperties(50); + } + + m_extraButtonCount = m_currentFlightStickProperties->ExtraButtonCount; + m_extraAxisCount = m_currentFlightStickProperties->ExtraAxisCount; + } + + m_currentFlightStickNeedsRefresh = false; + + Controller::ControllerAdded += ref new Windows::Foundation::EventHandler([=](Platform::Object^ /*sender*/, ControllerAddedEventArgs^ args) + { + if (args->Controller->Type == "Microsoft.Xbox.Input.FlightStick") + { + m_currentFlightStickNeedsRefresh = true; + } + }); + + Controller::ControllerRemoved += ref new Windows::Foundation::EventHandler([=](Platform::Object^ /*sender*/, ControllerRemovedEventArgs^ args) + { + if (args->Controller->Type == "Microsoft.Xbox.Input.FlightStick") + { + m_currentFlightStickNeedsRefresh = true; + } + }); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame"); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& ) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_currentFlightStickNeedsRefresh) + { + auto mostRecentFlightStick = FlightStickManager::GetFirstFlightStick(); + if (m_currentFlightStick != mostRecentFlightStick) + { + m_currentFlightStick = mostRecentFlightStick; + + if (m_currentFlightStick != nullptr) + { + m_currentFlightStickProperties = nullptr; + while (m_currentFlightStickProperties == nullptr) + { + // Need to retrieve properties again as the FlightStick has changed. + m_currentFlightStickProperties = m_currentFlightStick->GetProperties(50); + } + + m_extraButtonCount = m_currentFlightStickProperties->ExtraButtonCount; + m_extraAxisCount = m_currentFlightStickProperties->ExtraAxisCount; + } + } + m_currentFlightStickNeedsRefresh = false; + } + + if (m_currentFlightStick == nullptr) + { + m_buttonString.clear(); + PIXEndEvent(); + return; + } + + m_reading = m_currentFlightStick->GetRawCurrentReading(); + + m_buttonString = L"Buttons pressed: "; + + if ((m_reading.Buttons & FlightStickButtons::A) == FlightStickButtons::A) + { + m_buttonString += L"[A] "; + } + + if ((m_reading.Buttons & FlightStickButtons::B) == FlightStickButtons::B) + { + m_buttonString += L"[B] "; + } + + if ((m_reading.Buttons & FlightStickButtons::X) == FlightStickButtons::X) + { + m_buttonString += L"[X] "; + } + + if ((m_reading.Buttons & FlightStickButtons::Y) == FlightStickButtons::Y) + { + m_buttonString += L"[Y] "; + } + + if ((m_reading.Buttons & FlightStickButtons::FirePrimary) == FlightStickButtons::FirePrimary) + { + m_buttonString += L"Primary "; + } + + if ((m_reading.Buttons & FlightStickButtons::FireSecondary) == FlightStickButtons::FireSecondary) + { + m_buttonString += L"Secondary "; + } + + if ((m_reading.Buttons & FlightStickButtons::HatUp) == FlightStickButtons::HatUp) + { + m_buttonString += L"HatUp "; + } + + if ((m_reading.Buttons & FlightStickButtons::HatRight) == FlightStickButtons::HatRight) + { + m_buttonString += L"HatRight "; + } + + if ((m_reading.Buttons & FlightStickButtons::HatDown) == FlightStickButtons::HatDown) + { + m_buttonString += L"HatDown "; + } + + if ((m_reading.Buttons & FlightStickButtons::HatLeft) == FlightStickButtons::HatLeft) + { + m_buttonString += L"HatLeft "; + } + + m_stickRoll = m_reading.Roll; + m_stickPitch = m_reading.Pitch; + m_stickYaw = m_reading.Yaw; + m_throttle = m_reading.Throttle; + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto rect = m_deviceResources->GetOutputSize(); + auto safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + wchar_t tempString[256] = {}; + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), rect); + + if (!m_buttonString.empty()) + { + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), m_buttonString.c_str(), pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"Roll: %d", m_stickRoll); + m_font->DrawString(m_spriteBatch.get(), tempString, pos, ATG::Colors::White); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"Pitch: %d", m_stickPitch); + m_font->DrawString(m_spriteBatch.get(), tempString, pos, ATG::Colors::White); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"Yaw: %d", m_stickYaw); + m_font->DrawString(m_spriteBatch.get(), tempString, pos, ATG::Colors::White); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"Throttle: %u", m_throttle); + m_font->DrawString(m_spriteBatch.get(), tempString, pos, ATG::Colors::White); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"Extra Buttons: %u", m_extraButtonCount); + m_font->DrawString(m_spriteBatch.get(), tempString, pos, ATG::Colors::White); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"Extra Axis: %u", m_extraAxisCount); + m_font->DrawString(m_spriteBatch.get(), tempString, pos, ATG::Colors::White); + pos.y += m_font->GetLineSpacing() * 1.5f; + } + else + { + m_font->DrawString(m_spriteBatch.get(), L"No flight stick connected", pos, ATG::Colors::Orange); + } + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_24.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneController.spritefont"); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf()));; +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/FlightStick/FlightStick.h b/XDKSamples/System/FlightStick/FlightStick.h new file mode 100644 index 0000000000000000000000000000000000000000..e6914d906f834ad5547b74d77ee663e0acb169a4 --- /dev/null +++ b/XDKSamples/System/FlightStick/FlightStick.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// FlightStick.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Render objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; + + Microsoft::WRL::ComPtr m_background; + + //FlightStick states + Microsoft::Xbox::Input::RawFlightStickReading m_reading; + Microsoft::Xbox::Input::IFlightStick^ m_currentFlightStick; + Microsoft::Xbox::Input::IFlightStickProperties^ m_currentFlightStickProperties; + + std::atomic m_currentFlightStickNeedsRefresh; + std::wstring m_buttonString; + short m_stickRoll; + short m_stickPitch; + short m_stickYaw; + unsigned short m_throttle; + unsigned char m_extraButtonCount; + unsigned char m_extraAxisCount; + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; +}; diff --git a/XDKSamples/System/FlightStick/FlightStick.sln b/XDKSamples/System/FlightStick/FlightStick.sln new file mode 100644 index 0000000000000000000000000000000000000000..4f34bc558f1deb4b73c6001eb0cbc9dbaf662ac7 --- /dev/null +++ b/XDKSamples/System/FlightStick/FlightStick.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FlightStick", "FlightStick.vcxproj", "{E02A4300-4A99-4942-B968-FCF172750ED6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.ActiveCfg = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.Build.0 = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.Deploy.0 = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.ActiveCfg = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.Build.0 = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.Deploy.0 = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.ActiveCfg = Release|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.Build.0 = Release|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/FlightStick/FlightStick.vcxproj b/XDKSamples/System/FlightStick/FlightStick.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..68c68dcdebb3089c1f4f69a7ac06561edf6cb329 --- /dev/null +++ b/XDKSamples/System/FlightStick/FlightStick.vcxproj @@ -0,0 +1,230 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + FlightStick + {e02a4300-4a99-4942-b968-fcf172750ed6} + en-US + Win32Proj + title + + v140 + 14.0 + Native + 8.1 + FlightStick + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + $(OutDir)$(RootNamespace).winmd + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + Designer + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/FlightStick/FlightStick.vcxproj.filters b/XDKSamples/System/FlightStick/FlightStick.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..45f84972efc2d828e6263d31c715867d58a62435 --- /dev/null +++ b/XDKSamples/System/FlightStick/FlightStick.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + a7240d26-11f1-47e9-b2d4-b13651be07aa + + + bf720e03-8486-4c01-982d-366c98ba03e9 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {8d6d0512-aede-4a5c-a1b8-fd2fdcf54365} + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + Assets + + + \ No newline at end of file diff --git a/XDKSamples/System/FlightStick/Main.cpp b/XDKSamples/System/FlightStick/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e66618db6175b13b2e4b392f6437152b631a22b --- /dev/null +++ b/XDKSamples/System/FlightStick/Main.cpp @@ -0,0 +1,153 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FlightStick.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int __cdecl main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/XDKSamples/System/FlightStick/Package.appxmanifest b/XDKSamples/System/FlightStick/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..0e478535a7af0f8c36655cb7d4412a6eb6a0c05e --- /dev/null +++ b/XDKSamples/System/FlightStick/Package.appxmanifest @@ -0,0 +1,65 @@ + + + + + + + FlightStick + Xbox Advanced Technology Group + Assets\StoreLogo.png + FlightStick + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft.Xbox.Input.FlightStick.dll + + + + + diff --git a/XDKSamples/System/FlightStick/Readme.docx b/XDKSamples/System/FlightStick/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..8c57c9b5cce7252b5ff95263edc0555cdd1d3a22 Binary files /dev/null and b/XDKSamples/System/FlightStick/Readme.docx differ diff --git a/XDKSamples/System/FlightStick/StepTimer.h b/XDKSamples/System/FlightStick/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/FlightStick/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/FlightStick/Telemetry.h b/XDKSamples/System/FlightStick/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/FlightStick/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/FlightStick/pch.cpp b/XDKSamples/System/FlightStick/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/FlightStick/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/FlightStick/pch.h b/XDKSamples/System/FlightStick/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..27b6e87e7db19167963b7467a5ef1249de7a77c6 --- /dev/null +++ b/XDKSamples/System/FlightStick/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3F3F03F0 /* XDK Edition 170600 */ +#error This sample requires the June 2017 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GraphicsMemory.h" +#include "DDSTextureLoader.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow12.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..929c99046bd44ab836e6a6be8e34c7f5d56fc5ae Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow16.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..75749b77e6f9241d5a2487e5effecbc47ff7d14d Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow24.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow24.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..a61e452c9f74768307ce261530f1766d47c944b1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow24.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow32.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..520d1683ff649ff8fca559e06cf954de247a6448 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow64.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..2c03f00ce681d76cfd319b9819cd76216ccedcd9 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/ArialNarrow64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Logo.png b/XDKSamples/System/FrontPanelDemo/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Logo.png differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole12.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..c663c041b84380a749db1ac80c93b0ca851bd892 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole16.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..dfa661805bc09c62932874905be57d9b79efb5a3 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole24.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole24.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..9428c9356eb68dae993bd4a0966dc040ed78a2f6 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole24.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole32.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..f9a0d62eeca61295245434e4fbdadcfe8924865d Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole64.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..dee75b6b78700363777037d13ff04e22186a847b Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/LucidaConsole64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI12.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..462fc91aeee4f10d581d1d269079deea7fc047d3 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI16.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..f062aa1ef69373bb3102b81f03f05eadca2da511 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI24.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI24.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..33fbd9518a7250604c029c436e79a72ed6e49e1f Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI24.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI32.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..cf93ddc671b5b599fa56502c2804f7ab4bcbfbf4 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI64.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..19dfc9fd1672c7b2bffb76b589a7c476227f6254 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold12.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..9d11d901beaa12c9a9ba5655ef625d82ba71640e Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold16.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..44d024f4717709a837890ac136d27a8e3be3ec25 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold24.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold24.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..5958604b80396e11467ff3b513fd41922e96ed6f Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold24.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold32.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..70b8d1d7260d8fb24318114ccd45e09aba5638b0 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold64.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..0ab76846c492f65f233dbb9859671addbd6883a7 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Segoe_UI_bold64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/SmallLogo.png b/XDKSamples/System/FrontPanelDemo/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/SplashScreen.png b/XDKSamples/System/FrontPanelDemo/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/StoreLogo.png b/XDKSamples/System/FrontPanelDemo/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Symbols16.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Symbols16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..48b6bee58a7e4f2e76f81fbd7d165aeff13aae4e Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Symbols16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/Symbols32.rasterfont b/XDKSamples/System/FrontPanelDemo/Assets/Symbols32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..6dc4e7f15e7e2b475ce0d24bcd59361fc1651118 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/Symbols32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/WideLogo.png b/XDKSamples/System/FrontPanelDemo/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/WideLogo.png differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin1.sdkmesh b/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin1.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..561e73b773788878a17f4a4cdd37a9032c28142d Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin1.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin2.sdkmesh b/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin2.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..948ebe5a69bc06525361bd49e2a1840cd5a84429 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin2.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin3.sdkmesh b/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin3.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..13e54cf64ee706ec903ea337c6ef292ca39750eb Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/mesh/Dolphin3.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/mesh/seafloor.sdkmesh b/XDKSamples/System/FrontPanelDemo/Assets/mesh/seafloor.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..66824351e8de61c8c1cce44662da0cb2b5f7b991 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/mesh/seafloor.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust00.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust00.DDS new file mode 100644 index 0000000000000000000000000000000000000000..31efa47d60dd315b26f42ceceb2d3c24c8c31a1e Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust00.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust01.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust01.DDS new file mode 100644 index 0000000000000000000000000000000000000000..2faeee83477fc3bdb2a5626585ddf05a9f3d2ae6 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust01.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust02.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust02.DDS new file mode 100644 index 0000000000000000000000000000000000000000..bd45e401bcf6372bfc9a0bc3608e1869ba1edff3 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust02.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust03.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust03.DDS new file mode 100644 index 0000000000000000000000000000000000000000..76732486eaeafa8883ac565a4d4640b4845a5a0a Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust03.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust04.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust04.DDS new file mode 100644 index 0000000000000000000000000000000000000000..6383c5d0272d4c4afce4ff5d3b5ba1e846dbfbe6 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust04.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust05.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust05.DDS new file mode 100644 index 0000000000000000000000000000000000000000..502e699d7911505f2ab85a17b0a935a589e00edf Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust05.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust06.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust06.DDS new file mode 100644 index 0000000000000000000000000000000000000000..933e65388e51e84a6ff6040f61198b0fb39b8eb9 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust06.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust07.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust07.DDS new file mode 100644 index 0000000000000000000000000000000000000000..237844800622cc743ae42a60b77cc1da42f6293f Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust07.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust08.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust08.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c4ee24368242721386cacd30ce2b89189f8fb4ac Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust08.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust09.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust09.DDS new file mode 100644 index 0000000000000000000000000000000000000000..5e61c9b537765eceab299d79be123afb9b30f2f1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust09.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust10.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust10.DDS new file mode 100644 index 0000000000000000000000000000000000000000..61b991c0331537488258754f2aaf3df01788fb42 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust10.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust11.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust11.DDS new file mode 100644 index 0000000000000000000000000000000000000000..203ebd3fd4fdd6716304fd2b602eaa7ff07dce37 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust11.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust12.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust12.DDS new file mode 100644 index 0000000000000000000000000000000000000000..f4a475e0ca9992f0cfc8220148f61faebf6a2f98 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust12.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust13.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust13.DDS new file mode 100644 index 0000000000000000000000000000000000000000..208d522f37cc8f64f52f0fbeaf86040feeaf35cd Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust13.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust14.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust14.DDS new file mode 100644 index 0000000000000000000000000000000000000000..358f73ac5e768267801382c31d143a32f3d1d3d9 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust14.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust15.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust15.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c0e79a37ff7ce04d7613c22ae204e88d2ee9e017 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust15.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust16.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust16.DDS new file mode 100644 index 0000000000000000000000000000000000000000..2f489da5df38370001cf6b2c108dfd9769055ae4 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust16.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust17.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust17.DDS new file mode 100644 index 0000000000000000000000000000000000000000..9ab7873a0d475f1c506bffc748670b16c0e56956 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust17.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust18.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust18.DDS new file mode 100644 index 0000000000000000000000000000000000000000..f33f38e708b3fb81adac05569cad25d48d3cb3f3 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust18.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust19.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust19.DDS new file mode 100644 index 0000000000000000000000000000000000000000..16cb2571b05d1a06a31ee4283d26a74b394bf963 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust19.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust20.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust20.DDS new file mode 100644 index 0000000000000000000000000000000000000000..69cde8ebb01c223da636b11279a23b087b2499be Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust20.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust21.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust21.DDS new file mode 100644 index 0000000000000000000000000000000000000000..14725fd4c3830cfc61635771843290ca7c248d38 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust21.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust22.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust22.DDS new file mode 100644 index 0000000000000000000000000000000000000000..942ba661f24f165932d8899169ee9602a11dae03 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust22.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust23.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust23.DDS new file mode 100644 index 0000000000000000000000000000000000000000..fb962a9ea15731b93fb8daef5ebe038701506b8e Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust23.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust24.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust24.DDS new file mode 100644 index 0000000000000000000000000000000000000000..7b025fa813de6ed22363f8a02c82c751af0f1efc Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust24.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust25.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust25.DDS new file mode 100644 index 0000000000000000000000000000000000000000..31603e13eaadfcf0f42c6ca444eb34f2f4bd80a1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust25.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust26.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust26.DDS new file mode 100644 index 0000000000000000000000000000000000000000..077a7f88fb5d0a5088d8e4114a593c360f739992 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust26.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust27.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust27.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c951edfa647495f47214ef28e4074462ca34f99b Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust27.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust28.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust28.DDS new file mode 100644 index 0000000000000000000000000000000000000000..06c8e1a84720bc9b4f18d9b96ac4063f048e2035 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust28.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust29.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust29.DDS new file mode 100644 index 0000000000000000000000000000000000000000..5112c7abb0561629ec4ad9c38ff979a025ef7b9b Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust29.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust30.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust30.DDS new file mode 100644 index 0000000000000000000000000000000000000000..805497f0eb26545f6591c997a7b483037816f1b1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust30.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/caust31.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust31.DDS new file mode 100644 index 0000000000000000000000000000000000000000..d4c2dc4be5924119aee5e8140f2f7dcf6780bb58 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/caust31.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/dolphin.bmp b/XDKSamples/System/FrontPanelDemo/Assets/textures/dolphin.bmp new file mode 100644 index 0000000000000000000000000000000000000000..55dced6089b9739bb81953ca619dd824ce7bd7a0 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/dolphin.bmp differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/seafloor.bmp b/XDKSamples/System/FrontPanelDemo/Assets/textures/seafloor.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a3cc7cc578d4f340638b6617b0acf96ab4df33ca Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/seafloor.bmp differ diff --git a/XDKSamples/System/FrontPanelDemo/Assets/textures/ui2.DDS b/XDKSamples/System/FrontPanelDemo/Assets/textures/ui2.DDS new file mode 100644 index 0000000000000000000000000000000000000000..9f5b549e92693999e4fac0b675ae7f8b45080973 Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/Assets/textures/ui2.DDS differ diff --git a/XDKSamples/System/FrontPanelDemo/CausticsPS.hlsl b/XDKSamples/System/FrontPanelDemo/CausticsPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..1661f08577bfe7c0621f19fdba059acfb94f8621 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/CausticsPS.hlsl @@ -0,0 +1 @@ +#include "PixelShaders.hlsli" diff --git a/XDKSamples/System/FrontPanelDemo/DeviceResources.cpp b/XDKSamples/System/FrontPanelDemo/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29759abd16cd8674d19a6bdb3f66507f0e0990ea --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/DeviceResources.cpp @@ -0,0 +1,325 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_renderTarget->SetName(L"Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + } + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + + if (m_d3dGameDVRRenderTarget) + { + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + } + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/FrontPanelDemo/DeviceResources.h b/XDKSamples/System/FrontPanelDemo/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..1edd14523e9006c77bca692edc98d8732d1b0e67 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/DeviceResources.h @@ -0,0 +1,84 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + static const unsigned int c_EnableHDR = 0x4; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/Dolphin.cpp b/XDKSamples/System/FrontPanelDemo/Dolphin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc6b697c6c6cbeb71b6a78fb5b7b5f5a556cfea5 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/Dolphin.cpp @@ -0,0 +1,149 @@ +//-------------------------------------------------------------------------------------- +// Dolphin.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "Dolphin.h" +#include "ReadData.h" + +using namespace DirectX; + +Dolphin::Dolphin() + : m_world(XMMatrixIdentity()) + , m_translation(0, 0, 0) + , m_animationTime(0) + , m_blendWeight(0) + , m_primitiveType(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) + , m_vertexStride(0) + , m_indexCount(0) + , m_vertexFormat(DXGI_FORMAT_UNKNOWN) +{ + m_animationTime = float(rand() % 100); +} + +void Dolphin::Load(ID3D11Device *device, ID3D11DeviceContext *context, DirectX::EffectFactory *fxFactory) +{ + std::unique_ptr dolphinModel1 = Model::CreateFromSDKMESH(device, L"assets\\mesh\\Dolphin1.sdkmesh", *fxFactory); + std::unique_ptr dolphinModel2 = Model::CreateFromSDKMESH(device, L"assets\\mesh\\Dolphin2.sdkmesh", *fxFactory); + std::unique_ptr dolphinModel3 = Model::CreateFromSDKMESH(device, L"assets\\mesh\\Dolphin3.sdkmesh", *fxFactory); + + fxFactory->CreateTexture(L"dolphin.bmp", context, m_textureView.ReleaseAndGetAddressOf()); + + { + auto& meshes = dolphinModel1->meshes; + auto& meshParts = meshes[0]->meshParts; + auto& part = *meshParts[0]; + m_vb1 = part.vertexBuffer; + m_ib = part.indexBuffer; + m_primitiveType = part.primitiveType; + m_indexCount = part.indexCount; + m_vertexStride = part.vertexStride; + m_vertexFormat = part.indexFormat; + } + + { + auto& meshes = dolphinModel2->meshes; + auto& meshParts = meshes[0]->meshParts; + auto& part = *meshParts[0]; + m_vb2 = part.vertexBuffer; + } + + { + auto& meshes = dolphinModel3->meshes; + auto& meshParts = meshes[0]->meshParts; + auto& part = *meshParts[0]; + m_vb3 = part.vertexBuffer; + } + + { + auto blob = DX::ReadData(L"DolphinVS.cso"); + DX::ThrowIfFailed(device->CreateVertexShader(blob.data(), blob.size(), nullptr, m_vertexShader.ReleaseAndGetAddressOf())); + + const D3D11_INPUT_ELEMENT_DESC layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 1, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION", 2, DXGI_FORMAT_R32G32B32_FLOAT, 2, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 2, DXGI_FORMAT_R32G32B32_FLOAT, 2, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 2, DXGI_FORMAT_R32G32_FLOAT, 2, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + DX::ThrowIfFailed(device->CreateInputLayout(layout, _countof(layout), blob.data(), blob.size(), m_vertexLayout.ReleaseAndGetAddressOf())); + } +} + +void Dolphin::OnDeviceLost() +{ + m_textureView.Reset(); + m_vb1.Reset(); + m_vb2.Reset(); + m_vb3.Reset(); + m_ib.Reset(); + m_inputLayout.Reset(); + m_vertexShader.Reset(); + m_vertexLayout.Reset(); +} + +void Dolphin::Update(float, float elapsedTime) +{ + // update the animation time for the dolphin + m_animationTime += elapsedTime; + + // store the blend weight (this determines how fast the tale wags) + m_blendWeight = sinf(6 * m_animationTime); + + // compute our rotation matrices and combine them with scale into our world matrix + m_world = XMMatrixScaling(0.01f, 0.01f, 0.01f); + + // This rotation adds a little wiggle + m_world = XMMatrixMultiply(XMMatrixRotationZ(cos(4 * m_animationTime) / 6.0f), m_world); + + // Translate and then rotate to make the dolphin swim in a circle + m_world = XMMatrixMultiply(m_world, XMMatrixTranslation(0.0f, 0.0f, 8.0f)); + m_world = XMMatrixMultiply(m_world, XMMatrixRotationY(-m_animationTime / 2.0f)); + + // Perturb the dolphin's position in vertical direction so that it looks more "floaty" + m_world = XMMatrixMultiply(m_world, XMMatrixTranslation(0.0f, cos(4 * m_animationTime) / 3.0f, 0.0f)); +} + +void Dolphin::Render(ID3D11DeviceContext * d3dDeviceContext, ID3D11PixelShader * pixelShader, ID3D11ShaderResourceView * causticResourceView) +{ + unsigned int DolphinStrides[3] = { m_vertexStride, m_vertexStride, m_vertexStride }; + unsigned int DolphinOffsets[3] = { 0, 0, 0 }; + ID3D11Buffer *dolphinVBs[3] = { m_vb1.Get(), m_vb2.Get(), m_vb3.Get() }; + ID3D11ShaderResourceView *textureResourceView = m_textureView.Get(); + + d3dDeviceContext->IASetInputLayout(m_vertexLayout.Get()); + d3dDeviceContext->IASetVertexBuffers(0, 3, dolphinVBs, DolphinStrides, DolphinOffsets); + d3dDeviceContext->IASetIndexBuffer(m_ib.Get(), m_vertexFormat, 0); + d3dDeviceContext->IASetPrimitiveTopology(m_primitiveType); + d3dDeviceContext->VSSetShader(m_vertexShader.Get(), NULL, 0); + d3dDeviceContext->GSSetShader(NULL, NULL, 0); + d3dDeviceContext->PSSetShader(pixelShader, NULL, 0); + d3dDeviceContext->PSSetShaderResources(0, 1, &textureResourceView); + d3dDeviceContext->PSSetShaderResources(1, 1, &causticResourceView); + d3dDeviceContext->DrawIndexed(m_indexCount, 0, 0); +} + +void Dolphin::Translate(DirectX::XMVECTOR t) +{ + m_translation = XMVectorAdd(m_translation, t); +} + +DirectX::XMMATRIX Dolphin::GetWorld() +{ + // combine our existing world matrix with the translation + XMMATRIX result = XMMatrixMultiply(m_world, XMMatrixTranslationFromVector(m_translation)); + return result; +} + +float Dolphin::GetBlendWeight() +{ + return m_blendWeight; +} diff --git a/XDKSamples/System/FrontPanelDemo/Dolphin.h b/XDKSamples/System/FrontPanelDemo/Dolphin.h new file mode 100644 index 0000000000000000000000000000000000000000..ce312fa873824d7850d3e7caffe9390829438c19 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/Dolphin.h @@ -0,0 +1,48 @@ +//-------------------------------------------------------------------------------------- +// Dolphin.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +class Dolphin +{ +public: + Dolphin(); + + void Load(ID3D11Device *device, ID3D11DeviceContext *context, DirectX::EffectFactory *fxFactory); + + void OnDeviceLost(); + + void Update(float totalTime, float elapsedTime); + + void Render( + ID3D11DeviceContext *d3dDeviceContext, + ID3D11PixelShader *pixelShader, + ID3D11ShaderResourceView *causticResourceView); + + void Translate(DirectX::XMVECTOR t); + DirectX::XMMATRIX GetWorld(); + float GetBlendWeight(); + +private: + DirectX::SimpleMath::Vector3 m_translation; + DirectX::SimpleMath::Matrix m_world; + float m_animationTime; + float m_blendWeight; + + D3D11_PRIMITIVE_TOPOLOGY m_primitiveType; + unsigned int m_vertexStride; + unsigned int m_indexCount; + DXGI_FORMAT m_vertexFormat; + + Microsoft::WRL::ComPtr m_textureView; + Microsoft::WRL::ComPtr m_vb1; + Microsoft::WRL::ComPtr m_vb2; + Microsoft::WRL::ComPtr m_vb3; + Microsoft::WRL::ComPtr m_ib; + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_vertexLayout; +}; diff --git a/XDKSamples/System/FrontPanelDemo/DolphinVS.hlsl b/XDKSamples/System/FrontPanelDemo/DolphinVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..5d3f396188fc386b9e3430be17c0db79e5f16d9e --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/DolphinVS.hlsl @@ -0,0 +1 @@ +#include "VertexShaders.hlsli" diff --git a/XDKSamples/System/FrontPanelDemo/FontManager.cpp b/XDKSamples/System/FrontPanelDemo/FontManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e96e7ca1a25a418c22adc3e83585a5fcbb3b0346 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FontManager.cpp @@ -0,0 +1,38 @@ +//-------------------------------------------------------------------------------------- +// FontManager.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "FontManager.h" + +FontManager::FontManager() +{ +} + +FontManager &FontManager::Instance() +{ + static FontManager result; + return result; +} + +void FontManager::ClearCache() +{ + m_cachedFonts.clear(); +} + +ATG::RasterFont& FontManager::LoadFont(const wchar_t * fileName) +{ + auto itr = m_cachedFonts.find(fileName); + + if (itr != m_cachedFonts.end()) + { + return itr->second; + } + + m_cachedFonts[fileName] = ATG::RasterFont(fileName); + return m_cachedFonts[fileName]; +} + + diff --git a/XDKSamples/System/FrontPanelDemo/FontManager.h b/XDKSamples/System/FrontPanelDemo/FontManager.h new file mode 100644 index 0000000000000000000000000000000000000000..e64c964a3e71df5ca17e3e33fa4ec65cd1c1d0b2 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FontManager.h @@ -0,0 +1,29 @@ +//-------------------------------------------------------------------------------------- +// FontManager.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include + +#include "FrontPanel/RasterFont.h" + + +class FontManager +{ + FontManager(); + +public: + + static FontManager &Instance(); + + void ClearCache(); + + ATG::RasterFont &LoadFont(const wchar_t *fileName); + +private: + + std::unordered_map m_cachedFonts; +}; \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/FontViewerScreen.cpp b/XDKSamples/System/FrontPanelDemo/FontViewerScreen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf9fc408654f6974cb2d794f9d673daab83b9c56 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FontViewerScreen.cpp @@ -0,0 +1,137 @@ +//-------------------------------------------------------------------------------------- +// FontViewerScreen.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "FontViewerScreen.h" +#include "FontManager.h" +#include "FrontPanel/FrontPanelDisplay.h" + +using namespace ATG; + +const wchar_t *FontViewerScreen::s_defaultSampleText = L"ABCEDFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\n0123456789"; + +FontViewerScreen::FontViewerScreen(FrontPanelManager * owner, const wchar_t * faceName, unsigned titleHeight, const wchar_t * fileName) + : PanelScreen(owner) + , m_titleHeight(titleHeight) + , m_faceName(faceName) +{ + m_currentFont = m_heightToFontFile.cbegin(); + AddFontFile(titleHeight, fileName); +} + +void FontViewerScreen::AddFontFile(unsigned height, const wchar_t * fileName, const wchar_t *sampleText) +{ + unsigned curHeight = height; + if (m_currentFont != m_heightToFontFile.cend()) + { + curHeight = m_currentFont->first; + } + + FontData data{ fileName, sampleText }; + + m_heightToFontFile[height] = data; + + m_currentFont = m_heightToFontFile.find(curHeight); +} + +void FontViewerScreen::RenderFrontPanel() +{ + // Get the fonts + ATG::RasterFont &titleFont = FontManager::Instance().LoadFont(m_heightToFontFile[m_titleHeight].filename); + ATG::RasterFont &curFont = FontManager::Instance().LoadFont(m_currentFont->second.filename); + + auto &frontPanelDisplay = FrontPanelDisplay::Get(); + frontPanelDisplay.Clear(); + + BufferDesc fpDesc = frontPanelDisplay.GetBufferDescriptor(); + + int x = 0; + int y = 0; + + // Draw the title text + titleFont.DrawStringFmt(fpDesc, x, y, L"%s %i", m_faceName, m_currentFont->first); + y += titleFont.GetLineSpacing(); + + // Draw the sample text + curFont.DrawString(fpDesc, x, y, m_currentFont->second.sampleText); + + // Draw the navigation hints + { + x = fpDesc.width - m_nav.GetWidth(); + y = 0; + + if (m_currentFont != m_heightToFontFile.cbegin()) + { + m_nav.DrawLeftIndicator(fpDesc, x, y); + } + + auto tmp = m_currentFont; + ++tmp; + if (tmp != m_heightToFontFile.cend()) + { + m_nav.DrawRightIndicator(fpDesc, x, y); + } + + if (m_upNeighbor) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + + if (m_downNeighbor) + { + m_nav.DrawDownIndicator(fpDesc, x, y); + } + } + + frontPanelDisplay.Present(); +} + +bool FontViewerScreen::OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton) +{ + switch (whichButton) + { + case XBOX_FRONT_PANEL_BUTTONS_LEFT: + if (m_currentFont != m_heightToFontFile.cbegin()) + { + --m_currentFont; + RenderFrontPanel(); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_RIGHT: + { + auto tmp = m_currentFont; + ++tmp; + if (tmp != m_heightToFontFile.cend()) + { + m_currentFont = tmp; + RenderFrontPanel(); + return true; + } + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_UP: + if (m_upNeighbor) + { + m_upNeighbor->Resume(this); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_DOWN: + if (m_downNeighbor) + { + m_downNeighbor->Resume(this); + return true; + } + break; + } + + return false; +} diff --git a/XDKSamples/System/FrontPanelDemo/FontViewerScreen.h b/XDKSamples/System/FrontPanelDemo/FontViewerScreen.h new file mode 100644 index 0000000000000000000000000000000000000000..ada1a9dad34031fd362cb988045823e86463ecfc --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FontViewerScreen.h @@ -0,0 +1,40 @@ +//-------------------------------------------------------------------------------------- +// FontViewerScreen.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "PanelScreen.h" +#include "NavigationHint.h" +#include + +class FontViewerScreen : public PanelScreen +{ +public: + FontViewerScreen(FrontPanelManager *owner, const wchar_t *faceName, unsigned titleHeight, const wchar_t *fileName); + + void AddFontFile(unsigned height, const wchar_t *fileName, const wchar_t *sampleText = s_defaultSampleText); + + void RenderFrontPanel() override; + bool OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton) override; + + +private: + struct FontData + { + const wchar_t *filename; + const wchar_t *sampleText; + }; + + using HeightToFontFile = std::map; + + unsigned m_titleHeight; + const wchar_t *m_faceName; + HeightToFontFile m_heightToFontFile; + HeightToFontFile::const_iterator m_currentFont; + BasicNavigationHint m_nav; + + static const wchar_t *s_defaultSampleText; +}; \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.cpp b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f196fb7fe06981fe5b8e2d4af15601f10262054c --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.cpp @@ -0,0 +1,603 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelDemo.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelDemo.h" + +#include "ATGColors.h" +#include "ReadData.h" + +extern void ExitSample(); + +using namespace DirectX; +using namespace ATG; + +using Microsoft::WRL::ComPtr; + +namespace +{ + // Vertex data structure used to + // create a constant buffer. + struct VS_CONSTANT_BUFFER + { + XMVECTOR vZero; + XMVECTOR vConstants; + XMVECTOR vWeight; + + XMMATRIX matTranspose; + XMMATRIX matCameraTranspose; + XMMATRIX matViewTranspose; + XMMATRIX matProjTranspose; + + XMVECTOR vLight; + XMVECTOR vLightDolphinSpace; + XMVECTOR vDiffuse; + XMVECTOR vAmbient; + XMVECTOR vFog; + XMVECTOR vCaustics; + }; + + // Pixel data structure used to + // create a constant buffer. + struct PS_CONSTANT_BUFFER + { + float fAmbient[4]; + float fFogColor[4]; + }; + + static_assert((sizeof(VS_CONSTANT_BUFFER) % 16) == 0, "CB must be 16 byte aligned"); + static_assert((sizeof(PS_CONSTANT_BUFFER) % 16) == 0, "CB must be 16 byte aligned"); + + // Custom effect for sea floor + class SeaEffect : public IEffect + { + public: + SeaEffect(ID3D11Device* device, ID3D11PixelShader* pixelShader) : + m_pixelShader(pixelShader) + { + m_shaderBlob = DX::ReadData(L"SeaFloorVS.cso"); + DX::ThrowIfFailed(device->CreateVertexShader(m_shaderBlob.data(), m_shaderBlob.size(), nullptr, m_vertexShader.ReleaseAndGetAddressOf())); + } + + virtual void Apply(ID3D11DeviceContext* context) override + { + context->VSSetShader(m_vertexShader.Get(), nullptr, 0); + context->PSSetShader(m_pixelShader.Get(), nullptr, 0); + } + + virtual void GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength) override + { + *pShaderByteCode = m_shaderBlob.data(); + *pByteCodeLength = m_shaderBlob.size(); + } + + private: + ComPtr m_vertexShader; + ComPtr m_pixelShader; + std::vector m_shaderBlob; + }; +} + +Sample::Sample() + : m_frame(0), + m_paused(false), + m_wireframe(false), + m_currentCausticTextureView(0) +{ + m_deviceResources = std::make_unique(); + + // Set the water color to a nice blue. + SetWaterColor(0.0f, 0.5f, 1.0f); + + // Set the ambient light. + m_ambient[0] = 0.25f; + m_ambient[1] = 0.25f; + m_ambient[2] = 0.25f; + m_ambient[3] = 0.25f; +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_frontPanelManager.CreateScreens(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + if(m_frontPanelManager.IsAvailable()) + { + auto& addDolphinAction = m_frontPanelManager.CreateButtonAction( + L"Add Dolphin", + L"Add a new dolphin to the scene.", + [this]() { AddNewDolphins(1); } + ); + m_frontPanelManager.AssignActionToButton(addDolphinAction, XBOX_FRONT_PANEL_BUTTONS_BUTTON1); + + auto& removeDolphinAction = m_frontPanelManager.CreateButtonAction( + L"Remove Dolphin", + L"Remove a dolphin from the scene.", + [this]() { RemoveDolphin(); } + ); + m_frontPanelManager.AssignActionToButton(removeDolphinAction, XBOX_FRONT_PANEL_BUTTONS_BUTTON2); + + auto& clearDolphinsActions = m_frontPanelManager.CreateButtonAction( + L"Clear Dolphins", + L"Remove all remaining dolphins from\nthe scene.", + [this]() { ClearDolphins(); } + ); + m_frontPanelManager.AssignActionToButton(clearDolphinsActions, XBOX_FRONT_PANEL_BUTTONS_BUTTON3); + + auto& toggleWireframeAction = m_frontPanelManager.CreateButtonAction( + L"Toggle Wireframe", + L"Toggles between solid and wireframe\n" + L"rendering.", + [this]() { ToggleWireframe(); } + ); + m_frontPanelManager.AssignActionToButton(toggleWireframeAction, XBOX_FRONT_PANEL_BUTTONS_BUTTON4); + + auto& togglePauseAction = m_frontPanelManager.CreateButtonAction( + L"Pause/Resume", + L"Toggles between pausing and unpausing\n" + L"the simulation.", + [this]() { TogglePause(); } + ); + m_frontPanelManager.AssignActionToButton(togglePauseAction, XBOX_FRONT_PANEL_BUTTONS_BUTTON5); + + + m_frontPanelManager.CreateButtonAction( + L"Add 12 Dolphins", + L"Because, why not?", + [this]() { AddNewDolphins(12); } + ); + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + m_frontPanelManager.Update(timer); + + if (!m_paused) + { + float totalTime = float(timer.GetTotalSeconds()); + + // Update all the dolphins + for (unsigned int i = 0; i < m_dolphins.size(); i++) + m_dolphins[i]->Update(totalTime, elapsedTime); + + SetWaterColor(0.0f, 0.5f, 1.0f); + + // Animate the caustic textures + m_currentCausticTextureView = (static_cast(totalTime * 32)) % 32; + + auto context = m_deviceResources->GetD3DDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + + context->Map(m_VSConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + { + VS_CONSTANT_BUFFER *vertShaderConstData = (VS_CONSTANT_BUFFER*)mappedResource.pData; + + vertShaderConstData->vZero = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); + vertShaderConstData->vConstants = XMVectorSet(1.0f, 0.5f, 0.2f, 0.05f); + + // weight is for dolphins, so the value doesn't matter here (since we're setting it for the sea floor) + vertShaderConstData->vWeight = XMVectorSet(0, 0, 0, 0); + + // Lighting vectors (in world space and in dolphin model space) + // and other constants + vertShaderConstData->vLight = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vLightDolphinSpace = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vDiffuse = XMVectorSet(1.00f, 1.00f, 1.00f, 1.00f); + vertShaderConstData->vAmbient = XMVectorSet(m_ambient[0], m_ambient[1], m_ambient[2], m_ambient[3]); + vertShaderConstData->vFog = XMVectorSet(0.50f, 50.00f, 1.00f / (50.0f - 1.0f), 0.00f); + vertShaderConstData->vCaustics = XMVectorSet(0.05f, 0.05f, sinf(totalTime) / 8, cosf(totalTime) / 10); + + XMVECTOR vDeterminant; + XMMATRIX matDolphin = XMMatrixIdentity(); + XMMATRIX matDolphinInv = XMMatrixInverse(&vDeterminant, matDolphin); + vertShaderConstData->vLightDolphinSpace = XMVector4Normalize(XMVector4Transform(vertShaderConstData->vLight, matDolphinInv)); + + // Vertex shader operations use transposed matrices + XMMATRIX mat, matCamera; + matCamera = XMMatrixMultiply(matDolphin, XMLoadFloat4x4(&m_matView)); + mat = XMMatrixMultiply(matCamera, m_matProj); + vertShaderConstData->matTranspose = XMMatrixTranspose(mat); + vertShaderConstData->matCameraTranspose = XMMatrixTranspose(matCamera); + vertShaderConstData->matViewTranspose = XMMatrixTranspose(m_matView); + vertShaderConstData->matProjTranspose = XMMatrixTranspose(m_matProj); + + } + context->Unmap(m_VSConstantBuffer.Get(), 0); + + context->Map(m_PSConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + { + PS_CONSTANT_BUFFER* pPsConstData = (PS_CONSTANT_BUFFER*)mappedResource.pData; + + memcpy(pPsConstData->fAmbient, m_ambient, sizeof(m_ambient)); + memcpy(pPsConstData->fFogColor, m_waterColor, sizeof(m_waterColor)); + } + context->Unmap(m_PSConstantBuffer.Get(), 0); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + } + else + { + m_gamePadButtons.Reset(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + SetWaterColor(0.0f, 0.5f, 1.0f); + + // Set state + context->OMSetBlendState(m_states->Opaque(), 0, 0xffffffff); + context->RSSetState(m_wireframe ? m_states->Wireframe() : m_states->CullNone()); + context->OMSetDepthStencilState(m_states->DepthDefault(), 0); + + ID3D11SamplerState* pSamplers[] = { m_pSamplerMirror.Get(), m_states->LinearWrap() }; + context->PSSetSamplers(0, 2, pSamplers); + + context->VSSetConstantBuffers(0, 1, m_VSConstantBuffer.GetAddressOf()); + context->PSSetConstantBuffers(0, 1, m_PSConstantBuffer.GetAddressOf()); + + ///////////////////////////////////////////////////// + // + // Render sea floor + // + //////////////////////////////////////////////////// + assert(!m_seafloor->meshes.empty()); + assert(!m_seafloor->meshes[0]->meshParts.empty()); + m_seafloor->meshes[0]->meshParts[0]->Draw(context, m_seaEffect.get(), m_seaFloorVertexLayout.Get(), [&] + { + context->PSSetShaderResources(0, 1, m_seaFloorTextureView.GetAddressOf()); + context->PSSetShaderResources(1, 1, m_causticTextureViews[m_currentCausticTextureView].GetAddressOf()); + }); + + ///////////////////////////////////////////////////// + // + // Render Dolphins + // + //////////////////////////////////////////////////// + for (unsigned int i = 0; i < m_dolphins.size(); i++) + DrawDolphin(*m_dolphins[i].get()); + + m_frontPanelManager.GPURender(m_deviceResources.get()); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + // Use linear clear color for gamma-correct rendering. + context->ClearRenderTargetView(renderTarget, m_waterColor); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_frontPanelManager.CreateDeviceDependentResources(m_deviceResources.get()); + + //////////////////////////////// + // + // Create constant buffers + // + //////////////////////////////// + { + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = sizeof(VS_CONSTANT_BUFFER); + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cbDesc.MiscFlags = 0; + + DX::ThrowIfFailed(device->CreateBuffer(&cbDesc, NULL, m_VSConstantBuffer.GetAddressOf())); + + cbDesc.ByteWidth = sizeof(PS_CONSTANT_BUFFER); + + DX::ThrowIfFailed(device->CreateBuffer(&cbDesc, NULL, m_PSConstantBuffer.GetAddressOf())); + } + + m_fxFactory = std::make_unique(device); + m_fxFactory->SetDirectory(L"Assets\\textures"); + + ////////////////////////////// + // Create the dolphins + ////////////////////////////// + for (unsigned int i = 0; i < 4; i++) + { + AddNewDolphins(1); + } + + //////////////////////////////// + // + // Create the textures resources + // + //////////////////////////////// + m_fxFactory->CreateTexture(L"Seafloor.bmp", context, m_seaFloorTextureView.ReleaseAndGetAddressOf()); + + for (DWORD t = 0; t < 32; t++) + { + std::wstring path; + if (t < 10) + { + int count = _scwprintf(L"caust0%i.DDS", t); + path.resize(count + 1); + swprintf_s(&path[0], path.size(), L"caust0%i.DDS", t); + } + else + { + int count = _scwprintf(L"caust%i.DDS", t); + path.resize(count + 1); + swprintf_s(&path[0], path.size(), L"caust%i.DDS", t); + } + + m_fxFactory->CreateTexture(path.c_str(), context, m_causticTextureViews[t].ReleaseAndGetAddressOf()); + } + + // Create the common pixel shader + { + auto blob = DX::ReadData(L"CausticsPS.cso"); + DX::ThrowIfFailed(device->CreatePixelShader(blob.data(), blob.size(), nullptr, m_pixelShader.ReleaseAndGetAddressOf())); + } + + + //////////////////////////////// + // + // Create the mesh resources + // + //////////////////////////////// + + // Create sea floor objects + m_seafloor = Model::CreateFromSDKMESH(device, L"assets\\mesh\\seafloor.sdkmesh", *m_fxFactory); + + m_seaEffect = std::make_unique(device, m_pixelShader.Get()); + + m_seafloor->meshes[0]->meshParts[0]->CreateInputLayout(device, m_seaEffect.get(), m_seaFloorVertexLayout.ReleaseAndGetAddressOf()); + + { + D3D11_SAMPLER_DESC desc = {}; + desc.AddressU = D3D11_TEXTURE_ADDRESS_MIRROR; + desc.AddressV = D3D11_TEXTURE_ADDRESS_MIRROR; + desc.AddressW = D3D11_TEXTURE_ADDRESS_MIRROR; + desc.MaxLOD = D3D11_FLOAT32_MAX; + desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + DX::ThrowIfFailed(device->CreateSamplerState(&desc, m_pSamplerMirror.ReleaseAndGetAddressOf())); + } + + m_states = std::make_unique(device); + + // Determine the aspect ratio + float fAspectRatio = 1920.0f / 1080.0f; + + // Set the transform matrices + static const XMVECTORF32 c_vEyePt = { 0.0f, 0.0f, -5.0f, 0.0f }; + static const XMVECTORF32 c_vLookatPt = { 0.0f, 0.0f, 0.0f, 0.0f }; + static const XMVECTORF32 c_vUpVec = { 0.0f, 1.0f, 0.0f, 0.0f }; + + m_matView = XMMatrixLookAtLH(c_vEyePt, c_vLookatPt, c_vUpVec); + m_matProj = XMMatrixPerspectiveFovLH(XM_PI / 3, fAspectRatio, 1.0f, 10000.0f); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + m_frontPanelManager.CreateWindowSizeDependentResources(m_deviceResources.get()); +} +#pragma endregion + +void Sample::SetWaterColor(float red, float green, float blue) +{ + m_waterColor[0] = red; + m_waterColor[1] = green; + m_waterColor[2] = blue; + m_waterColor[3] = 1.0f; +} + +void Sample::DrawDolphin(Dolphin &dolphin) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + context->Map(m_VSConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + { + VS_CONSTANT_BUFFER* vertShaderConstData = (VS_CONSTANT_BUFFER*)mappedResource.pData; + + vertShaderConstData->vZero = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); + vertShaderConstData->vConstants = XMVectorSet(1.0f, 0.5f, 0.2f, 0.05f); + + FLOAT fBlendWeight = dolphin.GetBlendWeight(); + FLOAT fWeight1; + FLOAT fWeight2; + FLOAT fWeight3; + + if (fBlendWeight > 0.0f) + { + fWeight1 = fabsf(fBlendWeight); + fWeight2 = 1.0f - fabsf(fBlendWeight); + fWeight3 = 0.0f; + } + else + { + fWeight1 = 0.0f; + fWeight2 = 1.0f - fabsf(fBlendWeight); + fWeight3 = fabsf(fBlendWeight); + } + vertShaderConstData->vWeight = XMVectorSet(fWeight1, fWeight2, fWeight3, 0.0f); + + // Lighting vectors (in world space and in dolphin model space) + // and other constants + vertShaderConstData->vLight = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vLightDolphinSpace = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vDiffuse = XMVectorSet(1.00f, 1.00f, 1.00f, 1.00f); + vertShaderConstData->vAmbient = XMVectorSet(m_ambient[0], m_ambient[1], m_ambient[2], m_ambient[3]); + vertShaderConstData->vFog = XMVectorSet(0.50f, 50.00f, 1.00f / (50.0f - 1.0f), 0.00f); + + float totalSeconds = float(m_timer.GetTotalSeconds()); + vertShaderConstData->vCaustics = XMVectorSet(0.05f, 0.05f, sinf(totalSeconds) / 8, cosf(totalSeconds) / 10); + + XMVECTOR vDeterminant; + XMMATRIX matDolphin = dolphin.GetWorld(); + XMMATRIX matDolphinInv = XMMatrixInverse(&vDeterminant, matDolphin); + vertShaderConstData->vLightDolphinSpace = XMVector4Normalize(XMVector4Transform(vertShaderConstData->vLight, matDolphinInv)); + + // Vertex shader operations use transposed matrices + XMMATRIX mat, matCamera; + matCamera = XMMatrixMultiply(matDolphin, XMLoadFloat4x4(&m_matView)); + mat = XMMatrixMultiply(matCamera, m_matProj); + vertShaderConstData->matTranspose = XMMatrixTranspose(mat); + vertShaderConstData->matCameraTranspose = XMMatrixTranspose(matCamera); + vertShaderConstData->matViewTranspose = XMMatrixTranspose(m_matView); + vertShaderConstData->matProjTranspose = XMMatrixTranspose(m_matProj); + } + context->Unmap(m_VSConstantBuffer.Get(), 0); + + context->VSSetConstantBuffers(0, 1, m_VSConstantBuffer.GetAddressOf()); + dolphin.Render(context, m_pixelShader.Get(), m_causticTextureViews[m_currentCausticTextureView].Get()); +} + +void Sample::AddNewDolphins(unsigned count) +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + for (unsigned i = 0; i < count; ++i) + { + auto d = std::make_shared(); + d->Translate(XMVectorSet(0, -1.0f + 2.0f * float(rand() % 4), 10, 0)); + d->Load(device, context, m_fxFactory.get()); + m_dolphins.push_back(d); + } +} + +void Sample::RemoveDolphin() +{ + if (m_dolphins.size() > 0) + { + m_dolphins.pop_front(); + } +} + +void Sample::ClearDolphins() +{ + m_dolphins.clear(); +} + +void Sample::ToggleWireframe() +{ + m_wireframe = !m_wireframe; +} + +void Sample::TogglePause() +{ + m_paused = !m_paused; +} + +void Sample::PauseSimulation(bool pause) +{ + m_paused = pause; +} diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.h b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.h new file mode 100644 index 0000000000000000000000000000000000000000..40c9a1074501e3c14aa9eb26f6421f13416c22e7 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.h @@ -0,0 +1,107 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelDemo.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "FrontPanelManager.h" +#include "Dolphin.h" + +#include + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void SetWaterColor(float red, float green, float blue); + + void DrawDolphin(Dolphin &dolphin); + + void AddNewDolphins(unsigned count); + void RemoveDolphin(); + void ClearDolphins(); + void ToggleWireframe(); + void TogglePause(); + + void PauseSimulation(bool pause); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + bool m_paused; + bool m_wireframe; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // DirectXTK objects + std::unique_ptr m_states; + std::unique_ptr m_fxFactory; + + // Game state + Microsoft::WRL::ComPtr m_VSConstantBuffer; + Microsoft::WRL::ComPtr m_PSConstantBuffer; + + Microsoft::WRL::ComPtr m_pSamplerMirror; + + // Transform matrices + DirectX::SimpleMath::Matrix m_matView; + DirectX::SimpleMath::Matrix m_matProj; + + // array of dolphins + std::deque> m_dolphins; + + // Seafloor object + std::unique_ptr m_seafloor; + std::unique_ptr m_seaEffect; + Microsoft::WRL::ComPtr m_seaFloorTextureView; + Microsoft::WRL::ComPtr m_seaFloorVertexLayout; + + // Water caustics + Microsoft::WRL::ComPtr m_causticTextureViews[32]; + unsigned int m_currentCausticTextureView; + Microsoft::WRL::ComPtr m_pixelShader; + + float m_waterColor[4]; + float m_ambient[4]; + + // Front Panel Manager + FrontPanelManager m_frontPanelManager; +}; diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.sln b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.sln new file mode 100644 index 0000000000000000000000000000000000000000..c4d32a690ca37eda8a321917b1c5e4489c4329a7 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontPanelDemo", "FrontPanelDemo.vcxproj", "{5C3FC83C-6A95-46E6-941B-11D8C96783C9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Debug|Durango.ActiveCfg = Debug|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Debug|Durango.Build.0 = Debug|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Debug|Durango.Deploy.0 = Debug|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Profile|Durango.ActiveCfg = Profile|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Profile|Durango.Build.0 = Profile|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Profile|Durango.Deploy.0 = Profile|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Release|Durango.ActiveCfg = Release|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Release|Durango.Build.0 = Release|Durango + {5C3FC83C-6A95-46E6-941B-11D8C96783C9}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.vcxproj b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..ab18bc27d3ce47e0a87b52c6826d2b88ca02fc5b --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.vcxproj @@ -0,0 +1,436 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + FrontPanelDemo + {5c3fc83c-6a95-46e6-941b-11d8c96783c9} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + xboxfrontpanel.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + + + ShadeCausticsPixel + ShadeCausticsPixel + ShadeCausticsPixel + Pixel + Pixel + Pixel + + + ShadeDolphinVertex + ShadeDolphinVertex + ShadeDolphinVertex + Vertex + Vertex + Vertex + + + ShadeSeaFloorVertex + ShadeSeaFloorVertex + ShadeSeaFloorVertex + Vertex + Vertex + Vertex + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.vcxproj.filters b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..ae23cc2f0c282332567d8bc85bd615dd446109d8 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelDemo.vcxproj.filters @@ -0,0 +1,362 @@ + + + + + 34df894b-d953-4bb6-bc5c-2cf0f6052aa1 + + + 9b6def19-f875-4174-baea-6693f2761236 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {991acb5a-e7af-4bde-943c-7d976bb6c74e} + + + {5385b425-9a33-4bde-8e6a-f51bf384af51} + + + {adbbbdf0-b642-453f-8d2e-c9ef39b9ad2b} + + + {495be1c6-999b-49e9-9dbb-b50c0468ad5b} + + + {1d64bbea-53e4-4fda-8722-c98b3e460431} + + + {03669fc9-d9b2-4af4-b3aa-06807bc73436} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + FrontPanelScreens + + + FrontPanelScreens + + + FrontPanelScreens + + + FrontPanelScreens + + + FrontPanelScreens + + + + + + + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + ATG Tool Kit + + + FrontPanelScreens + + + FrontPanelScreens + + + FrontPanelScreens + + + FrontPanelScreens + + + FrontPanelScreens + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + + + Assets\mesh + + + Assets\mesh + + + Assets\mesh + + + Assets\mesh + + + shaders + + + shaders + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + Fonts + + + + Fonts + + + + + shaders + + + shaders + + + shaders + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelManager.cpp b/XDKSamples/System/FrontPanelDemo/FrontPanelManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fca7ed7648e91d727ea9e1aed8c2bf98b6b4513a --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelManager.cpp @@ -0,0 +1,431 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelManager.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "FrontPanelManager.h" +#include "TopLevelScreen.h" +#include "QuickActionScreen.h" +#include "QuickActionMappingScreen.h" +#include "FontViewerScreen.h" +#include "GPURenderScreen.h" + +using namespace ATG; + +using Microsoft::WRL::ComPtr; +using ButtonState = FrontPanelInput::ButtonStateTracker::ButtonState; + +FrontPanelManager::FrontPanelManager() + : m_currentPanelScreen(nullptr) +{ + + if (IsXboxFrontPanelAvailable()) + { + // Get the default front panel + DX::ThrowIfFailed(GetDefaultXboxFrontPanel(m_frontPanelControl.ReleaseAndGetAddressOf())); + + // Initialize the FrontPanelDisplay object + m_frontPanelDisplay = std::make_unique(m_frontPanelControl.Get()); + + // Initialize the FrontPanelInput object + m_frontPanelInput = std::make_unique(m_frontPanelControl.Get()); + + // Initialize the button assignments + for (int i = 0; i < m_buttonActionAssignments.size(); ++i) + { + m_buttonActionAssignments[i] = nullptr; + } + } +} + +void FrontPanelManager::CreateScreens() +{ + // Early out if there is no front panel + if (!m_frontPanelControl) + return; + + // Create the demo screens + auto& buttonActions = CreateChild( + L"Quick Actions", + L"1", + L"Scroll down to see the action assignment\n" + L"for each of the 5 front panel buttons."); + auto& fontViewer = CreateChild( + L"CPU Fonts", + L"2", + L"Scroll down to see the different font styles and\n" + L"scroll left and right to change the font size."); + auto& gpuRender = CreateChild( + L"GPU to Front Panel", + L"3", + L"Scroll down to use the GPU to render for the\n" + L"Front Panel."); + auto& buttonMappings = CreateChild( + L"Button Mappings", + L"4", + L"Scroll down to change the action assigment\n" + L"for each of the 5 front panel buttons.\n"); + + + auto& quickAction1 = CreateChild(XBOX_FRONT_PANEL_BUTTONS_BUTTON1); + auto& quickAction2 = CreateChild(XBOX_FRONT_PANEL_BUTTONS_BUTTON2); + auto& quickAction3 = CreateChild(XBOX_FRONT_PANEL_BUTTONS_BUTTON3); + auto& quickAction4 = CreateChild(XBOX_FRONT_PANEL_BUTTONS_BUTTON4); + auto& quickAction5 = CreateChild(XBOX_FRONT_PANEL_BUTTONS_BUTTON5); + + auto& fontViewArial = CreateChild(L"Arial Narrow", 16, L"assets\\ArialNarrow16.rasterfont"); + fontViewArial.AddFontFile(12, L"assets\\ArialNarrow12.rasterfont"); + fontViewArial.AddFontFile(24, L"assets\\ArialNarrow24.rasterfont"); + fontViewArial.AddFontFile(32, L"assets\\ArialNarrow32.rasterfont"); + fontViewArial.AddFontFile(64, L"assets\\ArialNarrow64.rasterfont"); + + auto& fontViewLucida = CreateChild(L"Lucida Console", 16, L"assets\\LucidaConsole16.rasterfont"); + fontViewLucida.AddFontFile(12, L"assets\\LucidaConsole12.rasterfont"); + fontViewLucida.AddFontFile(24, L"assets\\LucidaConsole24.rasterfont"); + fontViewLucida.AddFontFile(32, L"assets\\LucidaConsole32.rasterfont"); + fontViewLucida.AddFontFile(64, L"assets\\LucidaConsole64.rasterfont"); + + auto& fontViewSegoe = CreateChild(L"Segoe UI", 16, L"assets\\Segoe_UI16.rasterfont"); + fontViewSegoe.AddFontFile(12, L"assets\\Segoe_UI12.rasterfont"); + fontViewSegoe.AddFontFile(24, L"assets\\Segoe_UI24.rasterfont"); + fontViewSegoe.AddFontFile(32, L"assets\\Segoe_UI32.rasterfont"); + fontViewSegoe.AddFontFile(64, L"assets\\Segoe_UI64.rasterfont"); + + auto& fontViewSegoeBold = CreateChild(L"Segoe UI Bold", 16, L"assets\\Segoe_UI_bold16.rasterfont"); + fontViewSegoeBold.AddFontFile(12, L"assets\\Segoe_UI_bold12.rasterfont"); + fontViewSegoeBold.AddFontFile(24, L"assets\\Segoe_UI_bold24.rasterfont"); + fontViewSegoeBold.AddFontFile(32, L"assets\\Segoe_UI_bold32.rasterfont"); + fontViewSegoeBold.AddFontFile(64, L"assets\\Segoe_UI_bold64.rasterfont"); + + auto& gpuRenderScreen = CreateChild(); + + auto& quickActionMapper = CreateChild(); + + + buttonActions.SetLeftNeighbor(&buttonMappings); + buttonActions.SetRightNeighbor(&fontViewer); + buttonActions.SetDownNeighbor(&quickAction1); + + fontViewer.SetLeftNeighbor(&buttonActions); + fontViewer.SetRightNeighbor(&gpuRender); + fontViewer.SetDownNeighbor(&fontViewArial); + + fontViewArial.SetUpNeighbor(&fontViewer); + fontViewArial.SetDownNeighbor(&fontViewLucida); + + fontViewLucida.SetUpNeighbor(&fontViewArial); + fontViewLucida.SetDownNeighbor(&fontViewSegoe); + + fontViewSegoe.SetUpNeighbor(&fontViewLucida); + fontViewSegoe.SetDownNeighbor(&fontViewSegoeBold); + + fontViewSegoeBold.SetUpNeighbor(&fontViewSegoe); + + gpuRender.SetLeftNeighbor(&fontViewer); + gpuRender.SetRightNeighbor(&buttonMappings); + gpuRender.SetDownNeighbor(&gpuRenderScreen); + gpuRenderScreen.SetUpNeighbor(&gpuRender); + + buttonMappings.SetLeftNeighbor(&gpuRender); + buttonMappings.SetRightNeighbor(&buttonActions); + buttonMappings.SetDownNeighbor(&quickActionMapper); + + + quickAction1.SetUpNeighbor(&buttonActions); + quickAction1.SetLeftNeighbor(&quickAction5); + quickAction1.SetRightNeighbor(&quickAction2); + + quickAction2.SetUpNeighbor(&buttonActions); + quickAction2.SetLeftNeighbor(&quickAction1); + quickAction2.SetRightNeighbor(&quickAction3); + + quickAction3.SetUpNeighbor(&buttonActions); + quickAction3.SetLeftNeighbor(&quickAction2); + quickAction3.SetRightNeighbor(&quickAction4); + + quickAction4.SetUpNeighbor(&buttonActions); + quickAction4.SetLeftNeighbor(&quickAction3); + quickAction4.SetRightNeighbor(&quickAction5); + + quickAction5.SetUpNeighbor(&buttonActions); + quickAction5.SetLeftNeighbor(&quickAction4); + quickAction5.SetRightNeighbor(&quickAction1); + + quickActionMapper.SetUpNeighbor(&buttonMappings); + + buttonActions.Resume(nullptr); +} + +void FrontPanelManager::Update(DX::StepTimer const & timer) +{ + // Early out if there is no front panel + if (!m_frontPanelControl) + return; + + auto fpInput = m_frontPanelInput->GetState(); + m_frontPanelInputButtons.Update(fpInput); + + if (m_frontPanelInputButtons.buttonsChanged) + { + if(m_frontPanelInputButtons.button1 == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_BUTTON1); + + if (m_frontPanelInputButtons.button2 == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_BUTTON2); + + if (m_frontPanelInputButtons.button3 == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_BUTTON3); + + if (m_frontPanelInputButtons.button4 == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_BUTTON4); + + if (m_frontPanelInputButtons.button5 == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_BUTTON5); + + if (m_frontPanelInputButtons.dpadLeft == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_LEFT); + + if (m_frontPanelInputButtons.dpadRight == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_RIGHT); + + if (m_frontPanelInputButtons.dpadUp == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_UP); + + if (m_frontPanelInputButtons.dpadDown == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_DOWN); + + if (m_frontPanelInputButtons.buttonSelect == ButtonState::PRESSED) + OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS_SELECT); + } + + m_currentPanelScreen->Update(timer); +} + +void FrontPanelManager::Navigate(const PanelScreen & navToChild) +{ + // Early out if there is no front panel + if (!m_frontPanelControl) + return; + + SetAssignedLigts(); + + for (int i = 0; i < m_children.size(); ++i) + { + if (m_children[i].get() == &navToChild) + { + m_currentPanelScreen = m_children[i].get(); + return; + } + } +} + +bool FrontPanelManager::OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton) +{ + // Give the current screen first chance to handle the button press + if (m_currentPanelScreen->OnButtonPressed(whichButton)) + { + return true; + } + + // Otherwise handle it ourselves + switch (whichButton) + { + default: + break; + + case XBOX_FRONT_PANEL_BUTTONS_SELECT: + // Capture the front panel display (written in a number of file formats) + m_frontPanelDisplay->SaveDDSToFile(L"D:\\FrontPanelScreen.dds"); + m_frontPanelDisplay->SaveWICToFile(L"D:\\FrontPanelScreen.bmp", GUID_ContainerFormatBmp); + m_frontPanelDisplay->SaveWICToFile(L"D:\\FrontPanelScreen.gif", GUID_ContainerFormatGif); + m_frontPanelDisplay->SaveWICToFile(L"D:\\FrontPanelScreen.jpg", GUID_ContainerFormatJpeg); + m_frontPanelDisplay->SaveWICToFile(L"D:\\FrontPanelScreen.png", GUID_ContainerFormatPng); + m_frontPanelDisplay->SaveWICToFile(L"D:\\FrontPanelScreen.tif", GUID_ContainerFormatTiff); +#ifdef _DEBUG + OutputDebugStringA("Screenshot of front panel display written to development drive.\n"); +#endif + break; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON1: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON2: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON3: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON4: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON5: + return InvokeButtonAction(int(GetIndexForButtonId(whichButton)));; + } + + return false; +} + +bool FrontPanelManager::InvokeButtonAction(int buttonId) +{ + const ButtonAction *action = m_buttonActionAssignments[buttonId]; + if (action) + { + (*action).Invoke(); + return true; + } + + return false; +} + +void FrontPanelManager::SetAssignedLigts() const +{ + auto& fpi = FrontPanelInput::Get(); + fpi.SetLightStates(GetAssignedLights()); +} + +void FrontPanelManager::CreateDeviceDependentResources(DX::DeviceResources * deviceResources) +{ + // Early out if there is no front panel + if (!m_frontPanelControl) + return; + + for (int i = 0; i < m_children.size(); ++i) + { + m_children[i]->CreateDeviceDependentResources(deviceResources, m_frontPanelControl.Get()); + } +} + +void FrontPanelManager::CreateWindowSizeDependentResources(DX::DeviceResources * deviceResources) +{ + // Early out if there is no front panel + if (!m_frontPanelControl) + return; + + for (int i = 0; i < m_children.size(); ++i) + { + m_children[i]->CreateWindowSizeDependentResources(deviceResources); + } +} + +void FrontPanelManager::GPURender(DX::DeviceResources * deviceResources) +{ + // Early out if there is no front panel + if (!m_frontPanelControl) + return; + + m_currentPanelScreen->GPURender(deviceResources); +} + +size_t FrontPanelManager::GetIndexForButtonId(XBOX_FRONT_PANEL_BUTTONS buttonId) +{ + switch (buttonId) + { + default: + break; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON1: + // TODO: perform action for button1 + return 0; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON2: + // TODO: perform the action for button2 + return 1; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON3: + // TODO: perform the action for button3 + return 2; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON4: + // TODO: perform the action for button4 + return 3; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON5: + // TODO: perform the action for button5 + return 4; + } + + throw std::out_of_range("Invalid button Id"); +} + +size_t FrontPanelManager::ButtonActionCount() const +{ + return m_buttonActions.size(); +} + +const FrontPanelManager::ActionRecord &FrontPanelManager::operator[](size_t idx) const +{ + return *m_buttonActions[idx]; +} + +const FrontPanelManager::ActionRecord &FrontPanelManager::CreateButtonAction(const wchar_t * name, const wchar_t * description, std::function op) +{ + unsigned id = unsigned(m_buttonActions.size()); + + ButtonAction *action = new ButtonAction; + action->id = id; + action->name = name; + action->description = description; + action->Invoke = op; + + m_buttonActions.emplace_back(action); + return *m_buttonActions[id]; +} + +bool FrontPanelManager::IsActionAssigned(XBOX_FRONT_PANEL_BUTTONS buttonId) const +{ + size_t id = GetIndexForButtonId(buttonId); + const ButtonAction *action = m_buttonActionAssignments[id]; + return action != nullptr; +} + +const FrontPanelManager::ActionRecord &FrontPanelManager::GetActionAssignment(XBOX_FRONT_PANEL_BUTTONS buttonId) const +{ + size_t id = GetIndexForButtonId(buttonId); + const ButtonAction *action = m_buttonActionAssignments[id]; + if (action == nullptr) + { + throw std::exception("No action assignment for button"); + } + + return *action; +} + +void FrontPanelManager::AssignActionToButton(const ActionRecord &action, XBOX_FRONT_PANEL_BUTTONS buttonId) +{ + if (action.id >= m_buttonActions.size()) + { + throw std::range_error("Invalid button action ID"); + } + + size_t id = GetIndexForButtonId(buttonId); + m_buttonActionAssignments[id] = m_buttonActions[action.id].get(); + + SetAssignedLigts(); +} + +void FrontPanelManager::ClearActionAssignment(XBOX_FRONT_PANEL_BUTTONS buttonId) +{ + size_t id = GetIndexForButtonId(buttonId); + m_buttonActionAssignments[id] = nullptr; + + SetAssignedLigts(); +} + +XBOX_FRONT_PANEL_LIGHTS FrontPanelManager::GetAssignedLights() const +{ + XBOX_FRONT_PANEL_LIGHTS lights = XBOX_FRONT_PANEL_LIGHTS_NONE; + + for (int i = 0; i < m_buttonActionAssignments.size(); ++i) + { + if (m_buttonActionAssignments[i] != nullptr) + { + lights = static_cast(lights | XBOX_FRONT_PANEL_LIGHTS_LIGHT1 << i); + } + } + + return lights; +} + +void FrontPanelManager::AddChild(PanelScreen * child) +{ + m_children.emplace_back(child); + if (m_currentPanelScreen == nullptr) + { + m_currentPanelScreen = child; + } +} diff --git a/XDKSamples/System/FrontPanelDemo/FrontPanelManager.h b/XDKSamples/System/FrontPanelDemo/FrontPanelManager.h new file mode 100644 index 0000000000000000000000000000000000000000..7be0b6a3c1d8d78f45ef2a0bfaef12c1c08e0fdb --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/FrontPanelManager.h @@ -0,0 +1,91 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelManager.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "FrontPanel/FrontPanelDisplay.h" +#include "FrontPanel/FrontPanelInput.h" + +#include +#include + +#include "StepTimer.h" +#include "PanelScreen.h" + +class FrontPanelManager +{ +public: + FrontPanelManager(); + + void CreateScreens(); + + template + child_t &CreateChild(args... params) + { + child_t *child = new child_t( this, params... ); + AddChild(child); + return *child; + } + + void Update(DX::StepTimer const& timer); + void Navigate(const PanelScreen &navToChild); + + struct ActionRecord + { + unsigned id; + bool operator==(const ActionRecord &other) const + { + return id == other.id; + } + + std::wstring name; + std::wstring description; + }; + + static size_t GetIndexForButtonId(XBOX_FRONT_PANEL_BUTTONS buttonId); + + size_t ButtonActionCount() const; + const ActionRecord &operator[] (size_t idx) const; + const ActionRecord &CreateButtonAction(const wchar_t *name, const wchar_t *description, std::function op); + + bool IsActionAssigned(XBOX_FRONT_PANEL_BUTTONS buttonId) const; + const ActionRecord &GetActionAssignment(XBOX_FRONT_PANEL_BUTTONS buttonId) const; + void AssignActionToButton(const ActionRecord &action, XBOX_FRONT_PANEL_BUTTONS buttonId); + void ClearActionAssignment(XBOX_FRONT_PANEL_BUTTONS buttonId); + XBOX_FRONT_PANEL_LIGHTS GetAssignedLights() const; + void SetAssignedLigts() const; + + void CreateDeviceDependentResources(DX::DeviceResources *deviceResources); + void CreateWindowSizeDependentResources(DX::DeviceResources *deviceResources); + void GPURender(DX::DeviceResources *deviceResources); + + bool IsAvailable() const + { + return m_frontPanelControl; + } + +private: + void AddChild(PanelScreen *child); + bool OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton); + bool InvokeButtonAction(int buttonId); + + std::vector> m_children; + PanelScreen *m_currentPanelScreen; + + struct ButtonAction : public ActionRecord + { + std::function Invoke; + }; + + std::vector> m_buttonActions; + std::array m_buttonActionAssignments; + + // FrontPanel objects + Microsoft::WRL::ComPtr m_frontPanelControl; + std::unique_ptr m_frontPanelDisplay; + std::unique_ptr m_frontPanelInput; + ATG::FrontPanelInput::ButtonStateTracker m_frontPanelInputButtons; +}; \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/GPURenderScreen.cpp b/XDKSamples/System/FrontPanelDemo/GPURenderScreen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2224fd822f750a83b01a13f6850917d9d73ec33f --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/GPURenderScreen.cpp @@ -0,0 +1,85 @@ +//-------------------------------------------------------------------------------------- +// GPURenderScreen.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "GPURenderScreen.h" + +#include "FrontPanel/FrontPanelDisplay.h" + +using namespace ATG; + +GPURenderScreen::GPURenderScreen(FrontPanelManager * owner) + : PanelScreen(owner) +{ + // Set up the front panel render target + m_frontPanelRenderTarget = std::make_unique(); +} + +void GPURenderScreen::RenderFrontPanel() +{ + auto& frontPanelDisplay = FrontPanelDisplay::Get(); + BufferDesc fpDesc = frontPanelDisplay.GetBufferDescriptor(); + + // Draw the navigation hints + { + int x = fpDesc.width - m_nav.GetWidth(); + int y = 0; + + if (m_leftNeighbor) + { + m_nav.DrawLeftIndicator(fpDesc, x, y); + } + + if (m_rightNeighbor) + { + m_nav.DrawRightIndicator(fpDesc, x, y); + } + + if (m_upNeighbor) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + + if (m_downNeighbor) + { + m_nav.DrawDownIndicator(fpDesc, x, y); + } + } + + frontPanelDisplay.Present(); +} + +void GPURenderScreen::CreateDeviceDependentResources(DX::DeviceResources * deviceResources, IXboxFrontPanelControl * frontPanelControl) +{ + auto device = deviceResources->GetD3DDevice(); + + // Create the front panel render target resources + m_frontPanelRenderTarget->CreateDeviceDependentResources(frontPanelControl, device); +} + +void GPURenderScreen::CreateWindowSizeDependentResources(DX::DeviceResources * deviceResources) +{ + // Create a shader resource view for the main render target + auto device = deviceResources->GetD3DDevice(); + DX::ThrowIfFailed(device->CreateShaderResourceView(deviceResources->GetRenderTarget(), nullptr, m_mainRenderTargetSRV.GetAddressOf())); +} + + +void GPURenderScreen::GPURender(DX::DeviceResources * deviceResources) +{ + auto& frontPanelDisplay = FrontPanelDisplay::Get(); + BufferDesc fpDesc = frontPanelDisplay.GetBufferDescriptor(); + + auto context = deviceResources->GetD3DDeviceContext(); + + // Blit to the Front Panel render target and then present to the Front Panel + m_frontPanelRenderTarget->GPUBlit(context, m_mainRenderTargetSRV.Get()); + + m_frontPanelRenderTarget->CopyToBuffer(context, fpDesc); + + RenderFrontPanel(); +} diff --git a/XDKSamples/System/FrontPanelDemo/GPURenderScreen.h b/XDKSamples/System/FrontPanelDemo/GPURenderScreen.h new file mode 100644 index 0000000000000000000000000000000000000000..e9d265e449013fc39ef2af80eb9465b6bb47093b --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/GPURenderScreen.h @@ -0,0 +1,34 @@ +//-------------------------------------------------------------------------------------- +// GPURenderScreen.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "PanelScreen.h" +#include "NavigationHint.h" + +#include "FrontPanel/FrontPanelRenderTarget.h" + +class GPURenderScreen : public PanelScreen +{ +public: + GPURenderScreen(FrontPanelManager *owner); + void RenderFrontPanel() override; + void CreateDeviceDependentResources(DX::DeviceResources *deviceResources, IXboxFrontPanelControl *frontPanelControl) override; + void CreateWindowSizeDependentResources(DX::DeviceResources *deviceResources) override; + void GPURender(DX::DeviceResources *deviceResources) override; + +private: + // Front Panel Render Target + // Helper class to convert a GPU resource to grayscale and then render to the Front Panel + std::unique_ptr m_frontPanelRenderTarget; + + // Shader resource view for the whole screen + // This is the input to the FrontPanelRender target + Microsoft::WRL::ComPtr m_mainRenderTargetSRV; + + BasicNavigationHint m_nav; +}; + diff --git a/XDKSamples/System/FrontPanelDemo/Main.cpp b/XDKSamples/System/FrontPanelDemo/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cfd3e1ed9acff342c36bc24b3da78546734510e --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelDemo.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/NavigationHint.cpp b/XDKSamples/System/FrontPanelDemo/NavigationHint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8792b4895cecbb84ae3c337771ddbd52c822271e --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/NavigationHint.cpp @@ -0,0 +1,157 @@ +//-------------------------------------------------------------------------------------- +// NavigationHint.hpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "NavigationHint.h" +#include "FontManager.h" + +NavigationHint::NavigationHint( + const wchar_t *fontName, + wchar_t leftIndicator, + wchar_t rightIndicator, + wchar_t upIndicator, + wchar_t downIndicator, + unsigned clientWidth, + unsigned clientHeight) + : m_font(FontManager::Instance().LoadFont(fontName)) + , m_leftIndicator(leftIndicator) + , m_rightIndicator(rightIndicator) + , m_upIndicator(upIndicator) + , m_downIndicator(downIndicator) + , m_width(0) + , m_height(0) + , m_leftOffsetX(0) + , m_leftOffsetY(0) + , m_rightOffsetX(0) + , m_rightOffsetY(0) + , m_upOffsetX(0) + , m_upOffsetY(0) + , m_downOffsetX(0) + , m_downOffsetY(0) +{ + SetClientDimensions(clientWidth, clientHeight); +} + +NavigationHint::~NavigationHint() +{ +} + +void NavigationHint::DrawLeftIndicator(const ATG::BufferDesc &desc, int x, int y) +{ + if (m_leftIndicator) + { + m_font.DrawGlyph(desc, x + m_leftOffsetX, y + m_leftOffsetY, m_leftIndicator); + } +} + +void NavigationHint::DrawRightIndicator(const ATG::BufferDesc & desc, int x, int y) +{ + if (m_rightIndicator) + { + m_font.DrawGlyph(desc, x + m_rightOffsetX, y + m_rightOffsetY, m_rightIndicator); + } +} + +void NavigationHint::DrawUpIndicator(const ATG::BufferDesc & desc, int x, int y) +{ + if (m_upIndicator) + { + m_font.DrawGlyph(desc, x + m_upOffsetX, y + m_upOffsetY, m_upIndicator); + } +} + +void NavigationHint::DrawDownIndicator(const ATG::BufferDesc & desc, int x, int y) +{ + if (m_downIndicator) + { + m_font.DrawGlyph(desc, x + m_downOffsetX, y + m_downOffsetY, m_downIndicator); + } +} + +void NavigationHint::SetClientDimensions(unsigned clientWidth, unsigned clientHeight) +{ + unsigned upWidth = 0; + unsigned upHeight = 0; + if (m_upIndicator) + { + auto upMeasurement = m_font.MeasureGlyph(m_upIndicator); + upWidth = upMeasurement.right - upMeasurement.left; + upHeight = upMeasurement.bottom - upMeasurement.top; + } + + unsigned downWidth = 0; + unsigned downHeight = 0; + if(m_downIndicator) + { + auto downMeasurement = m_font.MeasureGlyph(m_downIndicator); + downWidth = downMeasurement.right - downMeasurement.left; + downHeight = downMeasurement.bottom - downMeasurement.top; + } + + unsigned leftWidth = 0; + unsigned leftHeight = 0; + if (m_leftIndicator) + { + auto leftMeasurement = m_font.MeasureGlyph(m_leftIndicator); + leftWidth = leftMeasurement.right - leftMeasurement.left; + leftHeight = leftMeasurement.bottom - leftMeasurement.top; + } + + unsigned rightWidth = 0; + unsigned rightHeight = 0; + if(m_rightIndicator) + { + auto rightMeasurement = m_font.MeasureGlyph(m_rightIndicator); + rightWidth = rightMeasurement.right - rightMeasurement.left; + rightHeight = rightMeasurement.bottom - rightMeasurement.top; + } + + unsigned cw = 1; + cw = std::max(cw, clientWidth); + cw = std::max(cw, upWidth + 2); + cw = std::max(cw, downWidth + 2); + + unsigned ch = 1; + ch = std::max(ch, clientHeight); + + // update the client rectangle + m_clientRect.left = leftWidth; + m_clientRect.right = leftWidth + cw; + m_clientRect.top = upHeight; + m_clientRect.bottom = upHeight + ch; + + // Compute the width and height + m_width = leftWidth + cw + rightWidth; + m_height = upHeight + ch + downHeight; + m_height = std::max(m_height, leftHeight); + m_height = std::max(m_height, rightHeight); + + // Compute the coordinates for the left indicator + m_leftOffsetX = 0; + m_leftOffsetY = static_cast(floor(0.5f + (m_height - leftHeight) / 2.0f)); + + // Compute the coordinates for the right indicator + m_rightOffsetX = leftWidth + cw; + m_rightOffsetY = static_cast(floor(0.5f + (m_height - rightHeight) / 2.0f)); + + // Compute the cooridates for the up indicator + m_upOffsetX = static_cast(floor(0.5f + (m_width - upWidth) / 2.0f)); + m_upOffsetY = 0; + + // Compute the coordinates for the down indicator + m_downOffsetX = static_cast(floor(0.5f + (m_width - downWidth) / 2.0f)); + m_downOffsetY = upHeight + ch; +} + +BasicNavigationHint::BasicNavigationHint() + : NavigationHint( + L"assets\\LucidaConsole12.rasterfont", + 0x25C4, 0x25BA, 0x25B2, 0x25BC, + 0, 0 + ) +{ +} diff --git a/XDKSamples/System/FrontPanelDemo/NavigationHint.h b/XDKSamples/System/FrontPanelDemo/NavigationHint.h new file mode 100644 index 0000000000000000000000000000000000000000..d9991b05c68c482fcc7ecb77491b3c1c1fe51cb9 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/NavigationHint.h @@ -0,0 +1,63 @@ +//-------------------------------------------------------------------------------------- +// NavigationHint.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "FrontPanel/RasterFont.h" + +class NavigationHint +{ +public: + NavigationHint( + const wchar_t *fontName, + wchar_t leftIndicator, + wchar_t rightIndicator, + wchar_t upIndicator, + wchar_t downIndicator, + unsigned clientWidth, + unsigned clientHeight); + + virtual ~NavigationHint(); + + unsigned GetWidth() const { return m_width; } + unsigned GetHeight() const { return m_height; } + + void DrawLeftIndicator(const ATG::BufferDesc &desc, int x, int y); + void DrawRightIndicator(const ATG::BufferDesc &desc, int x, int y); + void DrawUpIndicator(const ATG::BufferDesc &desc, int x, int y); + void DrawDownIndicator(const ATG::BufferDesc &desc, int x, int y); + + void SetClientDimensions(unsigned clientWidth, unsigned clientHeight); + RECT GetClientDimensions() const { return m_clientRect; } + +protected: + ATG::RasterFont &m_font; + const wchar_t m_leftIndicator; + const wchar_t m_rightIndicator; + const wchar_t m_upIndicator; + const wchar_t m_downIndicator; + + unsigned m_width; + unsigned m_height; + + RECT m_clientRect; + + unsigned m_leftOffsetX; + unsigned m_leftOffsetY; + unsigned m_rightOffsetX; + unsigned m_rightOffsetY; + unsigned m_upOffsetX; + unsigned m_upOffsetY; + unsigned m_downOffsetX; + unsigned m_downOffsetY; +}; + +class BasicNavigationHint : public NavigationHint +{ +public: + BasicNavigationHint(); +}; + diff --git a/XDKSamples/System/FrontPanelDemo/Package.appxmanifest b/XDKSamples/System/FrontPanelDemo/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..390a05b4eabe5cff3194c537c46b079d403edcc4 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + FrontPanelDemo + Xbox Advanced Technology Group + Assets\StoreLogo.png + FrontPanelDemo + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/FrontPanelDemo/PanelScreen.cpp b/XDKSamples/System/FrontPanelDemo/PanelScreen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c6d848c69b0a827baeaf2c18137e9cf090b6c8b --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/PanelScreen.cpp @@ -0,0 +1,113 @@ +//-------------------------------------------------------------------------------------- +// PanelScreen.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "PanelScreen.h" +#include "FrontPanelManager.h" +#include "StepTimer.h" + + +using namespace ATG; + + + +PanelScreen::~PanelScreen() +{ + m_owner = nullptr; +} + +void PanelScreen::Update(DX::StepTimer const &) +{ +} + +void PanelScreen::OnNeighborsChanged() +{ +} + +bool PanelScreen::OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton) +{ + switch (whichButton) + { + default: + break; + + case XBOX_FRONT_PANEL_BUTTONS_LEFT: + if (m_leftNeighbor) + { + m_leftNeighbor->Resume(this); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_RIGHT: + if (m_rightNeighbor) + { + m_rightNeighbor->Resume(this); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_UP: + if (m_upNeighbor) + { + m_upNeighbor->Resume(this); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_DOWN: + if (m_downNeighbor) + { + m_downNeighbor->Resume(this); + return true; + } + break; + } + return false; +} + +void PanelScreen::Resume(const PanelScreen *) +{ + m_owner->Navigate(*this); + RenderFrontPanel(); +} + +void PanelScreen::CreateDeviceDependentResources(DX::DeviceResources *, IXboxFrontPanelControl *) +{ +} + +void PanelScreen::CreateWindowSizeDependentResources(DX::DeviceResources *) +{ +} + +void PanelScreen::GPURender(DX::DeviceResources *) +{ +} + +void PanelScreen::SetLeftNeighbor(PanelScreen * leftNeighbor) +{ + m_leftNeighbor = leftNeighbor; + OnNeighborsChanged(); +} + +void PanelScreen::SetRightNeighbor(PanelScreen * rightNeighbor) +{ + m_rightNeighbor = rightNeighbor; + OnNeighborsChanged(); +} + +void PanelScreen::SetUpNeighbor(PanelScreen * upNeighbor) +{ + m_upNeighbor = upNeighbor; + OnNeighborsChanged(); +} + +void PanelScreen::SetDownNeighbor(PanelScreen * downNeighbor) +{ + m_downNeighbor = downNeighbor; + OnNeighborsChanged(); +} diff --git a/XDKSamples/System/FrontPanelDemo/PanelScreen.h b/XDKSamples/System/FrontPanelDemo/PanelScreen.h new file mode 100644 index 0000000000000000000000000000000000000000..746200f19e70d3771bb7f67ad25c306555423314 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/PanelScreen.h @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------------------------- +// PanelScreen.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include + +#include + +#include "FrontPanel/RasterFont.h" +#include "StepTimer.h" +#include "DeviceResources.h" + +class FrontPanelManager; + +class PanelScreen +{ +public: + PanelScreen(FrontPanelManager *owner) + : m_owner(owner) + , m_leftNeighbor(nullptr) + , m_rightNeighbor(nullptr) + , m_upNeighbor(nullptr) + , m_downNeighbor(nullptr) + { + } + + virtual ~PanelScreen(); + virtual void Update(DX::StepTimer const& timer); + virtual void OnNeighborsChanged(); + virtual bool OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton); + virtual void Resume(const PanelScreen *prevScreen); + + virtual void CreateDeviceDependentResources(DX::DeviceResources *deviceResources, IXboxFrontPanelControl *frontPanelControl); + virtual void CreateWindowSizeDependentResources(DX::DeviceResources *deviceResources); + virtual void GPURender(DX::DeviceResources *deviceResources); + + virtual void RenderFrontPanel() = 0; + + void SetLeftNeighbor(PanelScreen *leftNeighbor); + void SetRightNeighbor(PanelScreen *rightNeighbor); + void SetUpNeighbor(PanelScreen *upNeighbor); + void SetDownNeighbor(PanelScreen *downNeighbor); + +protected: + FrontPanelManager *m_owner; + PanelScreen *m_leftNeighbor; + PanelScreen *m_rightNeighbor; + PanelScreen *m_upNeighbor; + PanelScreen *m_downNeighbor; +}; + diff --git a/XDKSamples/System/FrontPanelDemo/PixelShaders.hlsli b/XDKSamples/System/FrontPanelDemo/PixelShaders.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..90c50371e13f4f4321efd68eec1beb19da2bda23 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/PixelShaders.hlsli @@ -0,0 +1,58 @@ +//-------------------------------------------------------------------------------------- +// PixelShaders.hlsli +// +// Pixel Shaders for the Dolphin sample +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +struct VSOUT +{ + float4 vPosition : SV_POSITION; + float4 vLightAndFog : COLOR0_center; // COLOR0.x = light, COLOR0.y = fog + float4 vTexCoords : TEXCOORD1; // TEXCOORD0.xy = basetex, TEXCOORD0.zw = caustictex +}; + +//-------------------------------------------------------------------------------------- +// Pixel shader constants +//-------------------------------------------------------------------------------------- +sampler SamplerSkin; +sampler SamplerCaustics; + +cbuffer cb0 +{ + uniform float3 g_vAmbient : register(c0); // Material ambient color + uniform float4 g_vFogColor : register(c1); // Fog color +} + +Texture2D TextureSkin; +Texture2D TextureCaustics; + +//-------------------------------------------------------------------------------------- +// Name: ShadeCausticsPixel() +// Desc: Pixel shader to add underwater caustics to a lit base texture. +//-------------------------------------------------------------------------------------- +float4 ShadeCausticsPixel(VSOUT Input) : SV_Target +{ + + // Decompress input values + float3 vLightColor = Input.vLightAndFog.xxx; + float fFogValue = Input.vLightAndFog.y; + float2 vBaseTexCoords = Input.vTexCoords.xy; + float2 vCausticTexCoords = Input.vTexCoords.zw; + + // Combine lighting, base texture and water caustics texture + float4 vDiffuse = TextureSkin.Sample(SamplerSkin, vBaseTexCoords); + float4 vCaustics = TextureCaustics.Sample(SamplerCaustics, vCausticTexCoords); + + // Combine lighting, base texture and water caustics texture + float4 PixelColor0 = vDiffuse * float4(vLightColor + g_vAmbient, 1); + float4 PixelColor1 = vCaustics * float4(vLightColor, 1); + + // Return color blended with fog + return lerp(g_vFogColor, PixelColor0 + PixelColor1, fFogValue); + + +} + + diff --git a/XDKSamples/System/FrontPanelDemo/QuickActionMappingScreen.cpp b/XDKSamples/System/FrontPanelDemo/QuickActionMappingScreen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20f613a865edfb545abde43cdf73914771b416f0 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/QuickActionMappingScreen.cpp @@ -0,0 +1,199 @@ +//-------------------------------------------------------------------------------------- +// QuickActionMappingScreen.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "QuickActionMappingScreen.h" +#include "FontManager.h" +#include "FrontPanelManager.h" + +#include "FrontPanel/FrontPanelDisplay.h" + +using namespace ATG; + +QuickActionMappingScreen::QuickActionMappingScreen(FrontPanelManager * owner) + : PanelScreen(owner) + , m_currentActionIndex(0) +{ +} + +void QuickActionMappingScreen::RenderFrontPanel() +{ + // Get the fonts + ATG::RasterFont &titleFont = FontManager::Instance().LoadFont(L"assets\\Segoe_UI_bold16.rasterfont"); + ATG::RasterFont &descriptionFont = FontManager::Instance().LoadFont(L"assets\\Segoe_UI16.rasterfont"); + ATG::RasterFont &symbolFont = FontManager::Instance().LoadFont(L"assets\\Symbols32.rasterfont"); + ATG::RasterFont &buttonFont = FontManager::Instance().LoadFont(L"assets\\Segoe_UI_bold24.rasterfont"); + + // Render to the front panel + auto& frontPanelDisplay = FrontPanelDisplay::Get(); + + frontPanelDisplay.Clear(); + + BufferDesc fpDesc = frontPanelDisplay.GetBufferDescriptor(); + + size_t count = m_owner->ButtonActionCount(); + int x = 0; + int y = 0; + + // Draw the title text + if(count == 0) + { + titleFont.DrawString(fpDesc, x, y, L"NO ACTIONS DEFINED"); + if (m_upNeighbor) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + frontPanelDisplay.Present(); + return; + } + else + { + titleFont.DrawString(fpDesc, x, y, L"Press any button to change/toggle:"); + } + y += titleFont.GetLineSpacing(); + x = 40; + + auto action = (*m_owner)[m_currentActionIndex]; + XBOX_FRONT_PANEL_BUTTONS btn = GetActionAssignment(action); + bool isActionAssigned = !!btn; + + // Draw the button graphic + { + wchar_t buttonGlyph = isActionAssigned ? wchar_t(FrontPanelManager::GetIndexForButtonId(btn)) + '1' : '?'; + int bx = 2; + int by = 16; + + symbolFont.DrawGlyph(fpDesc, bx, by, 0xE48C, isActionAssigned ? 0xF0 : 0x40); + + RECT rCrcl = symbolFont.MeasureGlyph(0xE48C); + float wCrcl = float(rCrcl.right - rCrcl.left); + float hCrcl = float(rCrcl.bottom - rCrcl.top); + + RECT rBtn = buttonFont.MeasureGlyph(buttonGlyph); + float wBtn = float(rBtn.right - rBtn.left); + float hBtn = float(rBtn.bottom - rBtn.top); + + bx += int(floor(0.5f + (wCrcl - wBtn) / 2.0f)); + by += int(floor(0.5f + (hCrcl - hBtn) / 2.0f)); + + buttonFont.DrawGlyph(fpDesc, bx, by, buttonGlyph, 0x00); + } + + // Draw the description text + descriptionFont.DrawStringFmt(fpDesc, x, y, L"%s\n%s", action.name.c_str(), action.description.c_str()); + + // Draw the navigation hints + { + x = fpDesc.width - m_nav.GetWidth(); + y = 0; + + if(m_currentActionIndex == 0) + { + if (m_upNeighbor) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + } + + if (m_currentActionIndex > 0) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + + if (m_currentActionIndex < count - 1) + { + m_nav.DrawDownIndicator(fpDesc, x, y); + } + } + + frontPanelDisplay.Present(); +} + +bool QuickActionMappingScreen::OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton) +{ + switch (whichButton) + { + default: + break; + + case XBOX_FRONT_PANEL_BUTTONS_UP: + if (m_currentActionIndex == 0) + { + if (m_upNeighbor) + { + m_upNeighbor->Resume(this); + return true; + } + } + else if (m_currentActionIndex > 0) + { + --m_currentActionIndex; + RenderFrontPanel(); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_DOWN: + if (m_currentActionIndex < m_owner->ButtonActionCount() - 1) + { + ++m_currentActionIndex; + RenderFrontPanel(); + return true; + } + break; + + case XBOX_FRONT_PANEL_BUTTONS_BUTTON1: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON2: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON3: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON4: + case XBOX_FRONT_PANEL_BUTTONS_BUTTON5: + if (unsigned(m_currentActionIndex) < m_owner->ButtonActionCount()) + { + return ChangeOrToggleAssignment(whichButton); + } + break; + + } + + return false; +} + +XBOX_FRONT_PANEL_BUTTONS QuickActionMappingScreen::GetActionAssignment(const FrontPanelManager::ActionRecord & action) const +{ + for (int i = XBOX_FRONT_PANEL_BUTTONS_BUTTON1; i <= XBOX_FRONT_PANEL_BUTTONS_BUTTON5; i = i << 1) + { + XBOX_FRONT_PANEL_BUTTONS btn = static_cast(i); + if (m_owner->IsActionAssigned(btn)) + { + auto& other = m_owner->GetActionAssignment(btn); + if (action == other) + return btn; + } + } + + return XBOX_FRONT_PANEL_BUTTONS_NONE; +} + +bool QuickActionMappingScreen::ChangeOrToggleAssignment(XBOX_FRONT_PANEL_BUTTONS whichButton) +{ + auto& action = (*m_owner)[m_currentActionIndex]; + XBOX_FRONT_PANEL_BUTTONS assignedButton = GetActionAssignment(action); + + // If the action is assigned, then clear the current assignement + if (assignedButton != XBOX_FRONT_PANEL_BUTTONS_NONE) + { + m_owner->ClearActionAssignment(assignedButton); + } + + // Assign the action to another button (but not the previous assigned button) + if (whichButton != assignedButton) + { + m_owner->AssignActionToButton(action, whichButton); + } + RenderFrontPanel(); + return true; +} diff --git a/XDKSamples/System/FrontPanelDemo/QuickActionMappingScreen.h b/XDKSamples/System/FrontPanelDemo/QuickActionMappingScreen.h new file mode 100644 index 0000000000000000000000000000000000000000..27c0b6bd616eb02acf03ebd8c8b49f604a079f33 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/QuickActionMappingScreen.h @@ -0,0 +1,26 @@ +//-------------------------------------------------------------------------------------- +// QuickActionMappingScreen.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "PanelScreen.h" +#include "NavigationHint.h" +#include "FrontPanelManager.h" + +class QuickActionMappingScreen : public PanelScreen +{ +public: + QuickActionMappingScreen(FrontPanelManager *owner); + void RenderFrontPanel() override; + bool OnButtonPressed(XBOX_FRONT_PANEL_BUTTONS whichButton) override; + +private: + XBOX_FRONT_PANEL_BUTTONS GetActionAssignment(const FrontPanelManager::ActionRecord &action) const; + bool ChangeOrToggleAssignment(XBOX_FRONT_PANEL_BUTTONS whichButton); + + int m_currentActionIndex; + BasicNavigationHint m_nav; +}; diff --git a/XDKSamples/System/FrontPanelDemo/QuickActionScreen.cpp b/XDKSamples/System/FrontPanelDemo/QuickActionScreen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3637d5240377133354cd01a9bbb9eb74a8ceaf0c --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/QuickActionScreen.cpp @@ -0,0 +1,148 @@ +//-------------------------------------------------------------------------------------- +// QuickActionScene.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "QuickActionScreen.h" +#include "FontManager.h" +#include "FrontPanelManager.h" + +#include "FrontPanel/FrontPanelInput.h" +#include "FrontPanel/FrontPanelDisplay.h" + +using namespace ATG; + +QuickActionScreen::QuickActionScreen(FrontPanelManager *owner, XBOX_FRONT_PANEL_BUTTONS buttonId) + : PanelScreen(owner) + , m_myButton(buttonId) + , m_curLightState(true) + , m_blinkSeconds(0.0f) +{ +} + +void QuickActionScreen::Update(DX::StepTimer const & timer) +{ + m_blinkSeconds += timer.GetElapsedSeconds(); + + if (m_blinkSeconds > 0.35f) + { + m_blinkSeconds = 0; + SetLightState(!m_curLightState); + } +} + +void QuickActionScreen::RenderFrontPanel() +{ + // Get the fonts + ATG::RasterFont &titleFont = FontManager::Instance().LoadFont(L"assets\\Segoe_UI_bold16.rasterfont"); + ATG::RasterFont &descriptionFont = FontManager::Instance().LoadFont(L"assets\\Segoe_UI16.rasterfont"); + ATG::RasterFont &symbolFont = FontManager::Instance().LoadFont(L"assets\\Symbols32.rasterfont"); + ATG::RasterFont &buttonFont = FontManager::Instance().LoadFont(L"assets\\Segoe_UI_bold24.rasterfont"); + + // Render to the front panel + auto& frontPanelDisplay = FrontPanelDisplay::Get(); + + frontPanelDisplay.Clear(); + + BufferDesc fpDesc = frontPanelDisplay.GetBufferDescriptor(); + + unsigned buttonIdx = unsigned(FrontPanelManager::GetIndexForButtonId(m_myButton)); + bool buttonHasAssignment = m_owner->IsActionAssigned(m_myButton); + int x = 40; + int y = 0; + + // Draw the title text + { + titleFont.DrawStringFmt(fpDesc, x, y, L"Button %i Action", buttonIdx + 1); + y += titleFont.GetLineSpacing(); + } + + // Draw the button graphic + { + wchar_t buttonGlyph = '1' + wchar_t(buttonIdx); + + int bx = 2; + int by = 16; + + symbolFont.DrawGlyph(fpDesc, bx, by, 0xE48C, buttonHasAssignment ? 0xF0 : 0x40); + + RECT rCrcl = symbolFont.MeasureGlyph(0xE48C); + float wCrcl = float(rCrcl.right - rCrcl.left); + float hCrcl = float(rCrcl.bottom - rCrcl.top); + + RECT rBtn = buttonFont.MeasureGlyph(buttonGlyph); + float wBtn = float(rBtn.right - rBtn.left); + float hBtn = float(rBtn.bottom - rBtn.top); + + bx += int(floor(0.5f + (wCrcl - wBtn) / 2.0f)); + by += int(floor(0.5f + (hCrcl - hBtn) / 2.0f)); + + buttonFont.DrawGlyph(fpDesc, bx, by, buttonGlyph, 0x00); + } + + // Draw the description text + { + if (buttonHasAssignment) + { + auto& assignment = m_owner->GetActionAssignment(m_myButton); + descriptionFont.DrawStringFmt(fpDesc, x, y, L"%s\n%s", assignment.name.c_str(), assignment.description.c_str()); + } + else + { + descriptionFont.DrawString(fpDesc, x, y, L"There is no action assigned to this\nbutton."); + } + } + + // Draw the navigation hints + { + x = fpDesc.width - m_nav.GetWidth(); + y = 0; + + if (m_leftNeighbor) + { + m_nav.DrawLeftIndicator(fpDesc, x, y); + } + + if (m_rightNeighbor) + { + m_nav.DrawRightIndicator(fpDesc, x, y); + } + + if (m_upNeighbor) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + + if (m_downNeighbor) + { + m_nav.DrawDownIndicator(fpDesc, x, y); + } + } + + frontPanelDisplay.Present(); + + // Turn on the light for the button corresponding to this screen + SetLightState(true); +} + +void QuickActionScreen::SetLightState(bool on) +{ + m_curLightState = on; + m_blinkSeconds = 0.0f; + + XBOX_FRONT_PANEL_LIGHTS lights = m_owner->GetAssignedLights(); + + if (on) + { + lights = static_cast(lights | m_myButton); + } + else + { + lights = static_cast(lights & ~m_myButton); + } + + FrontPanelInput::Get().SetLightStates(lights); +} diff --git a/XDKSamples/System/FrontPanelDemo/QuickActionScreen.h b/XDKSamples/System/FrontPanelDemo/QuickActionScreen.h new file mode 100644 index 0000000000000000000000000000000000000000..df3183d0886383ea501ca6fe9ade4e885b682b12 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/QuickActionScreen.h @@ -0,0 +1,29 @@ +//-------------------------------------------------------------------------------------- +// QuickActionScene.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "PanelScreen.h" +#include "NavigationHint.h" +#include "StepTimer.h" + +class QuickActionScreen : public PanelScreen +{ +public: + QuickActionScreen(FrontPanelManager *owner, XBOX_FRONT_PANEL_BUTTONS buttonId); + + void Update(DX::StepTimer const& timer) override; + void RenderFrontPanel() override; + +private: + void SetLightState(bool on); + + XBOX_FRONT_PANEL_BUTTONS m_myButton; + BasicNavigationHint m_nav; + bool m_curLightState; + double m_blinkSeconds; + +}; diff --git a/XDKSamples/System/FrontPanelDemo/SeaFloorVS.hlsl b/XDKSamples/System/FrontPanelDemo/SeaFloorVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..5d3f396188fc386b9e3430be17c0db79e5f16d9e --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/SeaFloorVS.hlsl @@ -0,0 +1 @@ +#include "VertexShaders.hlsli" diff --git a/XDKSamples/System/FrontPanelDemo/StepTimer.h b/XDKSamples/System/FrontPanelDemo/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/FrontPanelDemo/Telemetry.h b/XDKSamples/System/FrontPanelDemo/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/FrontPanelDemo/TopLevelScreen.cpp b/XDKSamples/System/FrontPanelDemo/TopLevelScreen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91517ba7e99a339fa4e275f0aacf21b43d10eed2 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/TopLevelScreen.cpp @@ -0,0 +1,103 @@ +//-------------------------------------------------------------------------------------- +// TopLevelScreen.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "TopLevelScreen.h" +#include "FontManager.h" +#include "FrontPanelManager.h" + +using namespace ATG; + +TopLevelScreen::TopLevelScreen(FrontPanelManager *owner, const wchar_t *titleText, const wchar_t *labelText, const wchar_t *descriptionText) + : PanelScreen(owner) + , m_titleText(titleText) + , m_labelText(labelText) + , m_descriptionText(descriptionText) + , m_titleFont(FontManager::Instance().LoadFont(L"assets\\Segoe_UI_bold24.rasterfont")) + , m_descriptionFont(FontManager::Instance().LoadFont(L"assets\\Segoe_UI16.rasterfont")) +{ + RECT r = m_titleFont.MeasureString(labelText); + + unsigned clientWidth = std::max(MIN_LABEL_WIDTH + RIGHT_LABEL_PADDING, static_cast(r.right - r.left)); + + m_nav.SetClientDimensions(clientWidth, r.bottom - r.top); +} + +void TopLevelScreen::RenderFrontPanel() +{ + // Render to the front panel + auto& frontPanelDisplay = FrontPanelDisplay::Get(); + + frontPanelDisplay.Clear(); + + BufferDesc fpDesc = frontPanelDisplay.GetBufferDescriptor(); + + int x = 0; + int y = 0; + + // Draw the title text + { + m_titleFont.DrawString(fpDesc, x, y, m_titleText.c_str()); + y += m_titleFont.GetLineSpacing(); + } + + // Draw the label text + { + int x0 = fpDesc.width - m_nav.GetWidth(); + int y0 = 0; + + RECT lRect = m_titleFont.MeasureString(m_labelText.c_str()); + float labelWidth = float(lRect.right - lRect.left); + float navWidth = float(m_nav.GetWidth()); + float labelHeight = float(lRect.bottom - lRect.top); + float navHeight = float(m_nav.GetHeight()); + + x0 += int(floor(0.5f + (navWidth - labelWidth) / 2.0f)) - RIGHT_LABEL_PADDING; + y0 += int(floor(0.5f + (navHeight - labelHeight) / 2.0f)); + m_titleFont.DrawString(fpDesc, x0, y0, m_labelText.c_str()); + } + + + // Draw the description text + m_descriptionFont.DrawString(fpDesc, x, y, m_descriptionText.c_str()); + + // Draw the navigation hints + { + x = fpDesc.width - m_nav.GetWidth(); + y = 0; + + if (m_leftNeighbor) + { + m_nav.DrawLeftIndicator(fpDesc, x, y); + } + + if (m_rightNeighbor) + { + m_nav.DrawRightIndicator(fpDesc, x, y); + } + + if (m_upNeighbor) + { + m_nav.DrawUpIndicator(fpDesc, x, y); + } + + if (m_downNeighbor) + { + m_nav.DrawDownIndicator(fpDesc, x, y); + } + } + + frontPanelDisplay.Present(); +} + +TopLevelScreen::TopLevelNavigationHint::TopLevelNavigationHint() + : NavigationHint( + L"assets\\Symbols16.rasterfont", + 0xE3B1, 0xE3B2, 0, 0, // 0xE3B0, 0xE3AF, + 0, 0 ) +{ +} diff --git a/XDKSamples/System/FrontPanelDemo/TopLevelScreen.h b/XDKSamples/System/FrontPanelDemo/TopLevelScreen.h new file mode 100644 index 0000000000000000000000000000000000000000..cb2223f6235bd758d00335ea1e91e46997d52a32 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/TopLevelScreen.h @@ -0,0 +1,39 @@ +//-------------------------------------------------------------------------------------- +// TopLevelScreen.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "PanelScreen.h" +#include "NavigationHint.h" + +class TopLevelScreen : public PanelScreen +{ +public: + TopLevelScreen( + FrontPanelManager *owner, + const wchar_t *titleText, + const wchar_t *labelText, + const wchar_t *descriptionText); + + void RenderFrontPanel() override; + +private: + class TopLevelNavigationHint : public NavigationHint + { + public: + TopLevelNavigationHint(); + }; + + const unsigned MIN_LABEL_WIDTH = 12; + const unsigned RIGHT_LABEL_PADDING = 1; + + std::wstring m_titleText; + std::wstring m_labelText; + std::wstring m_descriptionText; + ATG::RasterFont &m_titleFont; + ATG::RasterFont &m_descriptionFont; + TopLevelNavigationHint m_nav; +}; \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/VertexShaders.hlsli b/XDKSamples/System/FrontPanelDemo/VertexShaders.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..799be3bc40e17944272883a9a1b56b089a98e12e --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/VertexShaders.hlsli @@ -0,0 +1,123 @@ +//-------------------------------------------------------------------------------------- +// VertexShaders.hlsli +// +// Vertex Shaders for the Dolphin sample +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +struct VSOUT +{ + float4 vPosition : SV_POSITION; + float4 vLightAndFog : COLOR0_center; // COLOR0.x = light, COLOR0.y = fog + float4 vTexCoords : TEXCOORD1; // TEXCOORD0.xy = basetex, TEXCOORD0.zw = caustictex +}; + + +//-------------------------------------------------------------------------------------- +// Vertex shader constants +//-------------------------------------------------------------------------------------- + +cbuffer cb0 +{ + uniform float4 g_vZero : register(c0); // ( 0, 0, 0, 0 ) + uniform float4 g_vConstants : register(c1); // ( 1, 0.5, -, - ) + uniform float3 g_vBlendWeights : register(c2); // ( fWeight1, fWeight2, fWeight3, 0 ) + uniform float4x4 g_matWorldViewProj : register(c4); // world-view-projection matrix + uniform float4x4 g_matWorldView : register(c8); // world-view matrix + uniform float4x4 g_matView : register(c12); // view matrix + uniform float4x4 g_matProjection : register(c16); // projection matrix + uniform float3 g_vSeafloorLightDir : register(c20); // seafloor light direction + uniform float3 g_vDolphinLightDir : register(c21); // dolphin light direction + uniform float4 g_vDiffuse : register(c23); + uniform float4 g_vAmbient : register(c24); + uniform float4 g_vFogRange : register(c22); // ( x, fog_end, (1/(fog_end-fog_start)), x) + uniform float4 g_vTexGen : register(c25); +} + +//-------------------------------------------------------------------------------------- +// Name: ShadeSeaFloorVertex() +// Desc: Vertex shader for the seafloor +//-------------------------------------------------------------------------------------- +VSOUT ShadeSeaFloorVertex(const float3 vPosition : SV_POSITION, + const float3 vNormal : NORMAL, + const float2 vBaseTexCoords : TEXCOORD0) +{ + // Transform to view space (world matrix is identity) + float4 vViewPosition = mul(float4(vPosition, 1.0f), g_matView); + + // Transform to projection space + float4 vOutputPosition = mul(vViewPosition, g_matProjection); + + // Lighting calculation + float fLightValue = max(dot(vNormal, g_vSeafloorLightDir), g_vZero.x); + + // Generate water caustic tex coords from vertex xz position + float2 vCausticTexCoords = g_vTexGen.xx * vViewPosition.xz + g_vTexGen.zw; + + // Fog calculation: + float fFogValue = clamp((g_vFogRange.y - vViewPosition.z) * g_vFogRange.z, g_vZero.x, g_vConstants.x); + + // Compress output values + VSOUT Output; + Output.vPosition = vOutputPosition; + Output.vLightAndFog.x = fLightValue; + Output.vLightAndFog.y = fFogValue; + Output.vTexCoords.xy = 10 * vBaseTexCoords; + Output.vTexCoords.zw = vCausticTexCoords; + + Output.vLightAndFog.z = 0.0f; + Output.vLightAndFog.w = 0.0f; + + return Output; +} + + +//-------------------------------------------------------------------------------------- +// Name: ShadeDolphinVertex() +// Desc: Vertex shader for the dolphin +//-------------------------------------------------------------------------------------- +VSOUT ShadeDolphinVertex(const float3 vPosition0 : POSITION0, + const float3 vPosition1 : POSITION1, + const float3 vPosition2 : POSITION2, + const float3 vNormal0 : NORMAL0, + const float3 vNormal1 : NORMAL1, + const float3 vNormal2 : NORMAL2, + const float2 vBaseTexCoords : TEXCOORD0) +{ + // Tween the 3 positions (v0,v1,v2) into one position + float4 vModelPosition = float4(vPosition0 * g_vBlendWeights.x + vPosition1 * g_vBlendWeights.y + vPosition2 * g_vBlendWeights.z, 1.0f); + + // Transform position to the clipping space + float4 vOutputPosition = mul(vModelPosition, g_matWorldViewProj); + + // Transform position to the camera space + float4 vViewPosition = mul(vModelPosition, g_matWorldView); + + // Tween the 3 normals (v3,v4,v5) into one normal + float3 vModelNormal = vNormal0 * g_vBlendWeights.x + vNormal1 * g_vBlendWeights.y + vNormal2 * g_vBlendWeights.z; + + // Do the lighting calculation + float fLightValue = max(dot(vModelNormal, g_vDolphinLightDir), g_vZero.x); + + // Generate water caustic tex coords from vertex xz position + float2 vCausticTexCoords = g_vConstants.yy * vViewPosition.xz; + + // Fog calculation: + float fFogValue = clamp((g_vFogRange.y - vViewPosition.z) * g_vFogRange.z, g_vZero.x, g_vConstants.x); + + // Compress output values + VSOUT Output; + Output.vPosition = vOutputPosition; + Output.vLightAndFog.x = fLightValue; + Output.vLightAndFog.y = fFogValue; + Output.vTexCoords.xy = vBaseTexCoords; + Output.vTexCoords.zw = vCausticTexCoords; + + Output.vLightAndFog.z = 0.0f; + Output.vLightAndFog.w = 1.0f; + + return Output; +} + + diff --git a/XDKSamples/System/FrontPanelDemo/genfonts.cmd b/XDKSamples/System/FrontPanelDemo/genfonts.cmd new file mode 100644 index 0000000000000000000000000000000000000000..43d93c33707e175760aee0c258d42bda3b71e163 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/genfonts.cmd @@ -0,0 +1,42 @@ + +set RASTERFONTGEN=..\..\Tools\RasterFontGen\x64\Debug\RasterFontGen.exe + +set ANSI_RANGES=-cr:0x0020-0x007E -cr:0x00A0-0x00FF + +REM Lucida Console +%RASTERFONTGEN% -tf "Lucida Console" -h 12 -of "assets\LucidaConsole12.rasterfont" -ow +%RASTERFONTGEN% -tf "Lucida Console" -h 16 -of "assets\LucidaConsole16.rasterfont" -ow +%RASTERFONTGEN% -tf "Lucida Console" -h 24 -of "assets\LucidaConsole24.rasterfont" -ow +%RASTERFONTGEN% -tf "Lucida Console" -h 32 -of "assets\LucidaConsole32.rasterfont" -ow +%RASTERFONTGEN% -tf "Lucida Console" -h 64 -of "assets\LucidaConsole64.rasterfont" -ow + +REM Segoe UI +%RASTERFONTGEN% -tf "Segoe UI" -h 12 -of "assets\Segoe_UI12.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -h 16 -of "assets\Segoe_UI16.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -h 24 -of "assets\Segoe_UI24.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -h 32 -of "assets\Segoe_UI32.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -h 64 -of "assets\Segoe_UI64.rasterfont" -ow %ANSI_RANGES% + +REM Segoe UI Bold +%RASTERFONTGEN% -tf "Segoe UI" -w BOLD -h 12 -of "assets\Segoe_UI_bold12.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -w BOLD -h 16 -of "assets\Segoe_UI_bold16.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -w BOLD -h 24 -of "assets\Segoe_UI_bold24.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -w BOLD -h 32 -of "assets\Segoe_UI_bold32.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Segoe UI" -w BOLD -h 64 -of "assets\Segoe_UI_bold64.rasterfont" -ow %ANSI_RANGES% + +REM Arial Narrow +%RASTERFONTGEN% -tf "Arial Narrow" -h 12 -of "assets\ArialNarrow12.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Arial Narrow" -h 16 -of "assets\ArialNarrow16.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Arial Narrow" -h 24 -of "assets\ArialNarrow24.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Arial Narrow" -h 32 -of "assets\ArialNarrow32.rasterfont" -ow %ANSI_RANGES% +%RASTERFONTGEN% -tf "Arial Narrow" -h 64 -of "assets\ArialNarrow64.rasterfont" -ow %ANSI_RANGES% + + +REM Symbols + +set SYMBOL_RANGES=-cr:0xE3AF-0xE3B2 -cr:0xE48B-0xE48C + +%RASTERFONTGEN% -tf "Segoe Xbox MDL2 Assets" -h 16 -of "assets\Symbols16.rasterfont" -ow %SYMBOL_RANGES% +%RASTERFONTGEN% -tf "Segoe Xbox MDL2 Assets" -h 32 -of "assets\Symbols32.rasterfont" -ow %SYMBOL_RANGES% + + diff --git a/XDKSamples/System/FrontPanelDemo/pch.cpp b/XDKSamples/System/FrontPanelDemo/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/FrontPanelDemo/pch.h b/XDKSamples/System/FrontPanelDemo/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..92f8c6ee4d61af7d634feb3e78cac0178b8238c4 --- /dev/null +++ b/XDKSamples/System/FrontPanelDemo/pch.h @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This sample requires the March 2017 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "CommonStates.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Model.h" +#include "SimpleMath.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDemo/readme.docx b/XDKSamples/System/FrontPanelDemo/readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..8e5667c670aa635c5d43c109ad22ad0ad1f2af1e Binary files /dev/null and b/XDKSamples/System/FrontPanelDemo/readme.docx differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/Logo.png b/XDKSamples/System/FrontPanelDolphin/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/Logo.png differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/SmallLogo.png b/XDKSamples/System/FrontPanelDolphin/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/SplashScreen.png b/XDKSamples/System/FrontPanelDolphin/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/StoreLogo.png b/XDKSamples/System/FrontPanelDolphin/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/WideLogo.png b/XDKSamples/System/FrontPanelDolphin/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/WideLogo.png differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin1.sdkmesh b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin1.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..561e73b773788878a17f4a4cdd37a9032c28142d Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin1.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin2.sdkmesh b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin2.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..948ebe5a69bc06525361bd49e2a1840cd5a84429 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin2.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin3.sdkmesh b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin3.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..13e54cf64ee706ec903ea337c6ef292ca39750eb Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/Dolphin3.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/mesh/seafloor.sdkmesh b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/seafloor.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..66824351e8de61c8c1cce44662da0cb2b5f7b991 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/mesh/seafloor.sdkmesh differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust00.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust00.DDS new file mode 100644 index 0000000000000000000000000000000000000000..31efa47d60dd315b26f42ceceb2d3c24c8c31a1e Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust00.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust01.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust01.DDS new file mode 100644 index 0000000000000000000000000000000000000000..2faeee83477fc3bdb2a5626585ddf05a9f3d2ae6 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust01.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust02.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust02.DDS new file mode 100644 index 0000000000000000000000000000000000000000..bd45e401bcf6372bfc9a0bc3608e1869ba1edff3 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust02.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust03.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust03.DDS new file mode 100644 index 0000000000000000000000000000000000000000..76732486eaeafa8883ac565a4d4640b4845a5a0a Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust03.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust04.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust04.DDS new file mode 100644 index 0000000000000000000000000000000000000000..6383c5d0272d4c4afce4ff5d3b5ba1e846dbfbe6 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust04.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust05.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust05.DDS new file mode 100644 index 0000000000000000000000000000000000000000..502e699d7911505f2ab85a17b0a935a589e00edf Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust05.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust06.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust06.DDS new file mode 100644 index 0000000000000000000000000000000000000000..933e65388e51e84a6ff6040f61198b0fb39b8eb9 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust06.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust07.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust07.DDS new file mode 100644 index 0000000000000000000000000000000000000000..237844800622cc743ae42a60b77cc1da42f6293f Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust07.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust08.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust08.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c4ee24368242721386cacd30ce2b89189f8fb4ac Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust08.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust09.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust09.DDS new file mode 100644 index 0000000000000000000000000000000000000000..5e61c9b537765eceab299d79be123afb9b30f2f1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust09.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust10.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust10.DDS new file mode 100644 index 0000000000000000000000000000000000000000..61b991c0331537488258754f2aaf3df01788fb42 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust10.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust11.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust11.DDS new file mode 100644 index 0000000000000000000000000000000000000000..203ebd3fd4fdd6716304fd2b602eaa7ff07dce37 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust11.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust12.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust12.DDS new file mode 100644 index 0000000000000000000000000000000000000000..f4a475e0ca9992f0cfc8220148f61faebf6a2f98 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust12.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust13.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust13.DDS new file mode 100644 index 0000000000000000000000000000000000000000..208d522f37cc8f64f52f0fbeaf86040feeaf35cd Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust13.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust14.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust14.DDS new file mode 100644 index 0000000000000000000000000000000000000000..358f73ac5e768267801382c31d143a32f3d1d3d9 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust14.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust15.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust15.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c0e79a37ff7ce04d7613c22ae204e88d2ee9e017 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust15.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust16.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust16.DDS new file mode 100644 index 0000000000000000000000000000000000000000..2f489da5df38370001cf6b2c108dfd9769055ae4 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust16.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust17.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust17.DDS new file mode 100644 index 0000000000000000000000000000000000000000..9ab7873a0d475f1c506bffc748670b16c0e56956 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust17.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust18.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust18.DDS new file mode 100644 index 0000000000000000000000000000000000000000..f33f38e708b3fb81adac05569cad25d48d3cb3f3 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust18.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust19.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust19.DDS new file mode 100644 index 0000000000000000000000000000000000000000..16cb2571b05d1a06a31ee4283d26a74b394bf963 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust19.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust20.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust20.DDS new file mode 100644 index 0000000000000000000000000000000000000000..69cde8ebb01c223da636b11279a23b087b2499be Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust20.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust21.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust21.DDS new file mode 100644 index 0000000000000000000000000000000000000000..14725fd4c3830cfc61635771843290ca7c248d38 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust21.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust22.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust22.DDS new file mode 100644 index 0000000000000000000000000000000000000000..942ba661f24f165932d8899169ee9602a11dae03 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust22.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust23.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust23.DDS new file mode 100644 index 0000000000000000000000000000000000000000..fb962a9ea15731b93fb8daef5ebe038701506b8e Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust23.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust24.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust24.DDS new file mode 100644 index 0000000000000000000000000000000000000000..7b025fa813de6ed22363f8a02c82c751af0f1efc Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust24.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust25.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust25.DDS new file mode 100644 index 0000000000000000000000000000000000000000..31603e13eaadfcf0f42c6ca444eb34f2f4bd80a1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust25.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust26.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust26.DDS new file mode 100644 index 0000000000000000000000000000000000000000..077a7f88fb5d0a5088d8e4114a593c360f739992 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust26.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust27.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust27.DDS new file mode 100644 index 0000000000000000000000000000000000000000..c951edfa647495f47214ef28e4074462ca34f99b Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust27.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust28.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust28.DDS new file mode 100644 index 0000000000000000000000000000000000000000..06c8e1a84720bc9b4f18d9b96ac4063f048e2035 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust28.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust29.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust29.DDS new file mode 100644 index 0000000000000000000000000000000000000000..5112c7abb0561629ec4ad9c38ff979a025ef7b9b Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust29.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust30.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust30.DDS new file mode 100644 index 0000000000000000000000000000000000000000..805497f0eb26545f6591c997a7b483037816f1b1 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust30.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust31.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust31.DDS new file mode 100644 index 0000000000000000000000000000000000000000..d4c2dc4be5924119aee5e8140f2f7dcf6780bb58 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/caust31.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/dolphin.bmp b/XDKSamples/System/FrontPanelDolphin/Assets/textures/dolphin.bmp new file mode 100644 index 0000000000000000000000000000000000000000..55dced6089b9739bb81953ca619dd824ce7bd7a0 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/dolphin.bmp differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/seafloor.bmp b/XDKSamples/System/FrontPanelDolphin/Assets/textures/seafloor.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a3cc7cc578d4f340638b6617b0acf96ab4df33ca Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/seafloor.bmp differ diff --git a/XDKSamples/System/FrontPanelDolphin/Assets/textures/ui2.DDS b/XDKSamples/System/FrontPanelDolphin/Assets/textures/ui2.DDS new file mode 100644 index 0000000000000000000000000000000000000000..9f5b549e92693999e4fac0b675ae7f8b45080973 Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/Assets/textures/ui2.DDS differ diff --git a/XDKSamples/System/FrontPanelDolphin/CausticsPS.hlsl b/XDKSamples/System/FrontPanelDolphin/CausticsPS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..1661f08577bfe7c0621f19fdba059acfb94f8621 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/CausticsPS.hlsl @@ -0,0 +1 @@ +#include "PixelShaders.hlsli" diff --git a/XDKSamples/System/FrontPanelDolphin/DeviceResources.cpp b/XDKSamples/System/FrontPanelDolphin/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29759abd16cd8674d19a6bdb3f66507f0e0990ea --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/DeviceResources.cpp @@ -0,0 +1,325 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_renderTarget->SetName(L"Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + } + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + + if (m_d3dGameDVRRenderTarget) + { + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + } + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/FrontPanelDolphin/DeviceResources.h b/XDKSamples/System/FrontPanelDolphin/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..1edd14523e9006c77bca692edc98d8732d1b0e67 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/DeviceResources.h @@ -0,0 +1,84 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + static const unsigned int c_EnableHDR = 0x4; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDolphin/Dolphin.cpp b/XDKSamples/System/FrontPanelDolphin/Dolphin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc6b697c6c6cbeb71b6a78fb5b7b5f5a556cfea5 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/Dolphin.cpp @@ -0,0 +1,149 @@ +//-------------------------------------------------------------------------------------- +// Dolphin.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "Dolphin.h" +#include "ReadData.h" + +using namespace DirectX; + +Dolphin::Dolphin() + : m_world(XMMatrixIdentity()) + , m_translation(0, 0, 0) + , m_animationTime(0) + , m_blendWeight(0) + , m_primitiveType(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) + , m_vertexStride(0) + , m_indexCount(0) + , m_vertexFormat(DXGI_FORMAT_UNKNOWN) +{ + m_animationTime = float(rand() % 100); +} + +void Dolphin::Load(ID3D11Device *device, ID3D11DeviceContext *context, DirectX::EffectFactory *fxFactory) +{ + std::unique_ptr dolphinModel1 = Model::CreateFromSDKMESH(device, L"assets\\mesh\\Dolphin1.sdkmesh", *fxFactory); + std::unique_ptr dolphinModel2 = Model::CreateFromSDKMESH(device, L"assets\\mesh\\Dolphin2.sdkmesh", *fxFactory); + std::unique_ptr dolphinModel3 = Model::CreateFromSDKMESH(device, L"assets\\mesh\\Dolphin3.sdkmesh", *fxFactory); + + fxFactory->CreateTexture(L"dolphin.bmp", context, m_textureView.ReleaseAndGetAddressOf()); + + { + auto& meshes = dolphinModel1->meshes; + auto& meshParts = meshes[0]->meshParts; + auto& part = *meshParts[0]; + m_vb1 = part.vertexBuffer; + m_ib = part.indexBuffer; + m_primitiveType = part.primitiveType; + m_indexCount = part.indexCount; + m_vertexStride = part.vertexStride; + m_vertexFormat = part.indexFormat; + } + + { + auto& meshes = dolphinModel2->meshes; + auto& meshParts = meshes[0]->meshParts; + auto& part = *meshParts[0]; + m_vb2 = part.vertexBuffer; + } + + { + auto& meshes = dolphinModel3->meshes; + auto& meshParts = meshes[0]->meshParts; + auto& part = *meshParts[0]; + m_vb3 = part.vertexBuffer; + } + + { + auto blob = DX::ReadData(L"DolphinVS.cso"); + DX::ThrowIfFailed(device->CreateVertexShader(blob.data(), blob.size(), nullptr, m_vertexShader.ReleaseAndGetAddressOf())); + + const D3D11_INPUT_ELEMENT_DESC layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 1, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION", 2, DXGI_FORMAT_R32G32B32_FLOAT, 2, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 2, DXGI_FORMAT_R32G32B32_FLOAT, 2, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 2, DXGI_FORMAT_R32G32_FLOAT, 2, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + DX::ThrowIfFailed(device->CreateInputLayout(layout, _countof(layout), blob.data(), blob.size(), m_vertexLayout.ReleaseAndGetAddressOf())); + } +} + +void Dolphin::OnDeviceLost() +{ + m_textureView.Reset(); + m_vb1.Reset(); + m_vb2.Reset(); + m_vb3.Reset(); + m_ib.Reset(); + m_inputLayout.Reset(); + m_vertexShader.Reset(); + m_vertexLayout.Reset(); +} + +void Dolphin::Update(float, float elapsedTime) +{ + // update the animation time for the dolphin + m_animationTime += elapsedTime; + + // store the blend weight (this determines how fast the tale wags) + m_blendWeight = sinf(6 * m_animationTime); + + // compute our rotation matrices and combine them with scale into our world matrix + m_world = XMMatrixScaling(0.01f, 0.01f, 0.01f); + + // This rotation adds a little wiggle + m_world = XMMatrixMultiply(XMMatrixRotationZ(cos(4 * m_animationTime) / 6.0f), m_world); + + // Translate and then rotate to make the dolphin swim in a circle + m_world = XMMatrixMultiply(m_world, XMMatrixTranslation(0.0f, 0.0f, 8.0f)); + m_world = XMMatrixMultiply(m_world, XMMatrixRotationY(-m_animationTime / 2.0f)); + + // Perturb the dolphin's position in vertical direction so that it looks more "floaty" + m_world = XMMatrixMultiply(m_world, XMMatrixTranslation(0.0f, cos(4 * m_animationTime) / 3.0f, 0.0f)); +} + +void Dolphin::Render(ID3D11DeviceContext * d3dDeviceContext, ID3D11PixelShader * pixelShader, ID3D11ShaderResourceView * causticResourceView) +{ + unsigned int DolphinStrides[3] = { m_vertexStride, m_vertexStride, m_vertexStride }; + unsigned int DolphinOffsets[3] = { 0, 0, 0 }; + ID3D11Buffer *dolphinVBs[3] = { m_vb1.Get(), m_vb2.Get(), m_vb3.Get() }; + ID3D11ShaderResourceView *textureResourceView = m_textureView.Get(); + + d3dDeviceContext->IASetInputLayout(m_vertexLayout.Get()); + d3dDeviceContext->IASetVertexBuffers(0, 3, dolphinVBs, DolphinStrides, DolphinOffsets); + d3dDeviceContext->IASetIndexBuffer(m_ib.Get(), m_vertexFormat, 0); + d3dDeviceContext->IASetPrimitiveTopology(m_primitiveType); + d3dDeviceContext->VSSetShader(m_vertexShader.Get(), NULL, 0); + d3dDeviceContext->GSSetShader(NULL, NULL, 0); + d3dDeviceContext->PSSetShader(pixelShader, NULL, 0); + d3dDeviceContext->PSSetShaderResources(0, 1, &textureResourceView); + d3dDeviceContext->PSSetShaderResources(1, 1, &causticResourceView); + d3dDeviceContext->DrawIndexed(m_indexCount, 0, 0); +} + +void Dolphin::Translate(DirectX::XMVECTOR t) +{ + m_translation = XMVectorAdd(m_translation, t); +} + +DirectX::XMMATRIX Dolphin::GetWorld() +{ + // combine our existing world matrix with the translation + XMMATRIX result = XMMatrixMultiply(m_world, XMMatrixTranslationFromVector(m_translation)); + return result; +} + +float Dolphin::GetBlendWeight() +{ + return m_blendWeight; +} diff --git a/XDKSamples/System/FrontPanelDolphin/Dolphin.h b/XDKSamples/System/FrontPanelDolphin/Dolphin.h new file mode 100644 index 0000000000000000000000000000000000000000..ce312fa873824d7850d3e7caffe9390829438c19 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/Dolphin.h @@ -0,0 +1,48 @@ +//-------------------------------------------------------------------------------------- +// Dolphin.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +class Dolphin +{ +public: + Dolphin(); + + void Load(ID3D11Device *device, ID3D11DeviceContext *context, DirectX::EffectFactory *fxFactory); + + void OnDeviceLost(); + + void Update(float totalTime, float elapsedTime); + + void Render( + ID3D11DeviceContext *d3dDeviceContext, + ID3D11PixelShader *pixelShader, + ID3D11ShaderResourceView *causticResourceView); + + void Translate(DirectX::XMVECTOR t); + DirectX::XMMATRIX GetWorld(); + float GetBlendWeight(); + +private: + DirectX::SimpleMath::Vector3 m_translation; + DirectX::SimpleMath::Matrix m_world; + float m_animationTime; + float m_blendWeight; + + D3D11_PRIMITIVE_TOPOLOGY m_primitiveType; + unsigned int m_vertexStride; + unsigned int m_indexCount; + DXGI_FORMAT m_vertexFormat; + + Microsoft::WRL::ComPtr m_textureView; + Microsoft::WRL::ComPtr m_vb1; + Microsoft::WRL::ComPtr m_vb2; + Microsoft::WRL::ComPtr m_vb3; + Microsoft::WRL::ComPtr m_ib; + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_vertexLayout; +}; diff --git a/XDKSamples/System/FrontPanelDolphin/DolphinVS.hlsl b/XDKSamples/System/FrontPanelDolphin/DolphinVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..5d3f396188fc386b9e3430be17c0db79e5f16d9e --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/DolphinVS.hlsl @@ -0,0 +1 @@ +#include "VertexShaders.hlsli" diff --git a/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.cpp b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3d39588e5e23c06d0f3f5e4c892509729a294a9 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.cpp @@ -0,0 +1,559 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelDolphin.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelDolphin.h" + +#include "ATGColors.h" +#include "ReadData.h" + +extern void ExitSample(); + +using namespace DirectX; +using namespace ATG; + +using Microsoft::WRL::ComPtr; + +namespace +{ + // Vertex data structure used to + // create a constant buffer. + struct VS_CONSTANT_BUFFER + { + XMVECTOR vZero; + XMVECTOR vConstants; + XMVECTOR vWeight; + + XMMATRIX matTranspose; + XMMATRIX matCameraTranspose; + XMMATRIX matViewTranspose; + XMMATRIX matProjTranspose; + + XMVECTOR vLight; + XMVECTOR vLightDolphinSpace; + XMVECTOR vDiffuse; + XMVECTOR vAmbient; + XMVECTOR vFog; + XMVECTOR vCaustics; + }; + + // Pixel data structure used to + // create a constant buffer. + struct PS_CONSTANT_BUFFER + { + float fAmbient[4]; + float fFogColor[4]; + }; + + static_assert((sizeof(VS_CONSTANT_BUFFER) % 16) == 0, "CB must be 16 byte aligned"); + static_assert((sizeof(PS_CONSTANT_BUFFER) % 16) == 0, "CB must be 16 byte aligned"); + + // Custom effect for sea floor + class SeaEffect : public IEffect + { + public: + SeaEffect(ID3D11Device* device, ID3D11PixelShader* pixelShader) : + m_pixelShader(pixelShader) + { + m_shaderBlob = DX::ReadData(L"SeaFloorVS.cso"); + DX::ThrowIfFailed(device->CreateVertexShader(m_shaderBlob.data(), m_shaderBlob.size(), nullptr, m_vertexShader.ReleaseAndGetAddressOf())); + } + + virtual void Apply(ID3D11DeviceContext* context) override + { + context->VSSetShader(m_vertexShader.Get(), nullptr, 0); + context->PSSetShader(m_pixelShader.Get(), nullptr, 0); + } + + virtual void GetVertexShaderBytecode(_Out_ void const** pShaderByteCode, _Out_ size_t* pByteCodeLength) override + { + *pShaderByteCode = m_shaderBlob.data(); + *pByteCodeLength = m_shaderBlob.size(); + } + + private: + ComPtr m_vertexShader; + ComPtr m_pixelShader; + std::vector m_shaderBlob; + }; +} + +Sample::Sample() + : m_frame(0), + m_currentCausticTextureView(0) +{ + m_deviceResources = std::make_unique(); + + // Create the dolphins + for (unsigned int i = 0; i < m_dolphins.size(); i++) + { + auto d = std::make_shared(); + d->Translate(XMVectorSet(0, -1.0f + 2.0f * static_cast(i), 10, 0)); + m_dolphins[i] = d; + } + + // Set the water color to a nice blue. + SetWaterColor(0.0f, 0.5f, 1.0f); + + // Set the ambient light. + m_ambient[0] = 0.25f; + m_ambient[1] = 0.25f; + m_ambient[2] = 0.25f; + m_ambient[3] = 0.25f; + + if (IsXboxFrontPanelAvailable()) + { + // Construct the front panel render target + m_frontPanelRenderTarget = std::make_unique(); + + // Get the default front panel + DX::ThrowIfFailed(GetDefaultXboxFrontPanel(m_frontPanelControl.ReleaseAndGetAddressOf())); + + // Initialize the FrontPanelDisplay object + m_frontPanelDisplay = std::make_unique(m_frontPanelControl.Get()); + + // Intiailize the FrontPanelInput object + m_frontPanelInput = std::make_unique(m_frontPanelControl.Get()); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + float totalTime = float(timer.GetTotalSeconds()); + + // Update all the dolphins + for (unsigned int i = 0; i < m_dolphins.size(); i++) + m_dolphins[i]->Update(totalTime, elapsedTime); + + SetWaterColor(0.0f, 0.5f, 1.0f); + + // Animate the caustic textures + m_currentCausticTextureView = (static_cast(totalTime *32)) % 32; + + auto context = m_deviceResources->GetD3DDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + + context->Map(m_VSConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + { + VS_CONSTANT_BUFFER *vertShaderConstData = (VS_CONSTANT_BUFFER*)mappedResource.pData; + + vertShaderConstData->vZero = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); + vertShaderConstData->vConstants = XMVectorSet(1.0f, 0.5f, 0.2f, 0.05f); + + // weight is for dolphins, so the value doesn't matter here (since we're setting it for the sea floor) + vertShaderConstData->vWeight = XMVectorSet(0, 0, 0, 0); + + // Lighting vectors (in world space and in dolphin model space) + // and other constants + vertShaderConstData->vLight = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vLightDolphinSpace = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vDiffuse = XMVectorSet(1.00f, 1.00f, 1.00f, 1.00f); + vertShaderConstData->vAmbient = XMVectorSet(m_ambient[0], m_ambient[1], m_ambient[2], m_ambient[3]); + vertShaderConstData->vFog = XMVectorSet(0.50f, 50.00f, 1.00f / (50.0f - 1.0f), 0.00f); + vertShaderConstData->vCaustics = XMVectorSet(0.05f, 0.05f, sinf(totalTime) / 8, cosf(totalTime) / 10); + + XMVECTOR vDeterminant; + XMMATRIX matDolphin = XMMatrixIdentity(); + XMMATRIX matDolphinInv = XMMatrixInverse(&vDeterminant, matDolphin); + vertShaderConstData->vLightDolphinSpace = XMVector4Normalize(XMVector4Transform(vertShaderConstData->vLight, matDolphinInv)); + + // Vertex shader operations use transposed matrices + XMMATRIX mat, matCamera; + matCamera = XMMatrixMultiply(matDolphin, XMLoadFloat4x4(&m_matView)); + mat = XMMatrixMultiply(matCamera, m_matProj); + vertShaderConstData->matTranspose = XMMatrixTranspose(mat); + vertShaderConstData->matCameraTranspose = XMMatrixTranspose(matCamera); + vertShaderConstData->matViewTranspose = XMMatrixTranspose(m_matView); + vertShaderConstData->matProjTranspose = XMMatrixTranspose(m_matProj); + + } + context->Unmap(m_VSConstantBuffer.Get(), 0); + + context->Map(m_PSConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + { + PS_CONSTANT_BUFFER* pPsConstData = (PS_CONSTANT_BUFFER*)mappedResource.pData; + + memcpy(pPsConstData->fAmbient, m_ambient, sizeof(m_ambient)); + memcpy(pPsConstData->fFogColor, m_waterColor, sizeof(m_waterColor)); + } + context->Unmap(m_PSConstantBuffer.Get(), 0); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + // Use the front panel select button to capture the front panel dispaly + if (m_frontPanelControl) + { + auto fpInput = m_frontPanelInput->GetState(); + m_frontPanelInputButtons.Update(fpInput); + + using ButtonState = FrontPanelInput::ButtonStateTracker::ButtonState; + + if (m_frontPanelInputButtons.buttonSelect == ButtonState::PRESSED) + { + m_frontPanelDisplay->SaveDDSToFile(L"D:\\FrontPanelScreen.dds"); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + SetWaterColor(0.0f, 0.5f, 1.0f); + + // Set state + context->OMSetBlendState(m_states->Opaque(), 0, 0xffffffff); + context->RSSetState(m_states->CullNone()); + context->OMSetDepthStencilState(m_states->DepthDefault(), 0); + + ID3D11SamplerState* pSamplers[] = { m_pSamplerMirror.Get(), m_states->LinearWrap() }; + context->PSSetSamplers(0, 2, pSamplers); + + context->VSSetConstantBuffers(0, 1, m_VSConstantBuffer.GetAddressOf()); + context->PSSetConstantBuffers(0, 1, m_PSConstantBuffer.GetAddressOf()); + + ///////////////////////////////////////////////////// + // + // Render sea floor + // + //////////////////////////////////////////////////// + assert(!m_seafloor->meshes.empty()); + assert(!m_seafloor->meshes[0]->meshParts.empty()); + m_seafloor->meshes[0]->meshParts[0]->Draw(context, m_seaEffect.get(), m_seaFloorVertexLayout.Get(), [&] + { + context->PSSetShaderResources(0, 1, m_seaFloorTextureView.GetAddressOf()); + context->PSSetShaderResources(1, 1, m_causticTextureViews[m_currentCausticTextureView].GetAddressOf()); + }); + + ///////////////////////////////////////////////////// + // + // Render Dolphins + // + //////////////////////////////////////////////////// + for (unsigned int i = 0; i < m_dolphins.size(); i++) + DrawDolphin(*m_dolphins[i].get()); + + if (m_frontPanelControl) + { + // Blit to the Front Panel render target and then present to the Front Panel + m_frontPanelRenderTarget->GPUBlit(m_deviceResources->GetD3DDeviceContext(), m_mainRenderTargetSRV.Get()); + auto fpDesc = m_frontPanelDisplay->GetBufferDescriptor(); + m_frontPanelRenderTarget->CopyToBuffer(m_deviceResources->GetD3DDeviceContext(), fpDesc); + m_frontPanelDisplay->Present(); + } + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + // Use linear clear color for gamma-correct rendering. + context->ClearRenderTargetView(renderTarget, m_waterColor); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + auto context = m_deviceResources->GetD3DDeviceContext(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + // Set up for rendering to the front panel via the GPU + if (m_frontPanelControl) + { + // Create the front panel render target resources + m_frontPanelRenderTarget->CreateDeviceDependentResources(m_frontPanelControl.Get(), device); + } + + //////////////////////////////// + // + // Create constant buffers + // + //////////////////////////////// + { + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = sizeof(VS_CONSTANT_BUFFER); + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cbDesc.MiscFlags = 0; + + DX::ThrowIfFailed(device->CreateBuffer(&cbDesc, NULL, m_VSConstantBuffer.GetAddressOf())); + + cbDesc.ByteWidth = sizeof(PS_CONSTANT_BUFFER); + + DX::ThrowIfFailed(device->CreateBuffer(&cbDesc, NULL, m_PSConstantBuffer.GetAddressOf())); + } + + m_fxFactory = std::make_unique(device); + m_fxFactory->SetDirectory(L"Assets\\textures"); + + //////////////////////////////// + // + // Load the dolphins + // + ////////////////////////////// + for (unsigned int i = 0; i < m_dolphins.size(); i++) + m_dolphins[i]->Load(device, context, m_fxFactory.get()); + + //////////////////////////////// + // + // Create the textures resources + // + //////////////////////////////// + m_fxFactory->CreateTexture(L"Seafloor.bmp", context, m_seaFloorTextureView.ReleaseAndGetAddressOf()); + + for (DWORD t = 0; t < 32; t++) + { + std::wstring path; + if (t < 10) + { + int count = _scwprintf(L"caust0%i.DDS", t); + path.resize(count + 1); + swprintf_s(&path[0], path.size(), L"caust0%i.DDS", t); + } + else + { + int count = _scwprintf(L"caust%i.DDS", t); + path.resize(count + 1); + swprintf_s(&path[0], path.size(), L"caust%i.DDS", t); + } + + m_fxFactory->CreateTexture(path.c_str(), context, m_causticTextureViews[t].ReleaseAndGetAddressOf()); + } + + // Create the common pixel shader + { + auto blob = DX::ReadData(L"CausticsPS.cso"); + DX::ThrowIfFailed(device->CreatePixelShader(blob.data(), blob.size(), nullptr, m_pixelShader.ReleaseAndGetAddressOf())); + } + + //////////////////////////////// + // + // Create the mesh resources + // + //////////////////////////////// + + // Create sea floor objects + m_seafloor = Model::CreateFromSDKMESH(device, L"assets\\mesh\\seafloor.sdkmesh", *m_fxFactory); + + m_seaEffect = std::make_unique(device, m_pixelShader.Get()); + + m_seafloor->meshes[0]->meshParts[0]->CreateInputLayout(device, m_seaEffect.get(), m_seaFloorVertexLayout.ReleaseAndGetAddressOf()); + + m_states = std::make_unique(device); + + { + D3D11_SAMPLER_DESC desc = {}; + desc.AddressU = D3D11_TEXTURE_ADDRESS_MIRROR; + desc.AddressV = D3D11_TEXTURE_ADDRESS_MIRROR; + desc.AddressW = D3D11_TEXTURE_ADDRESS_MIRROR; + desc.MaxLOD = D3D11_FLOAT32_MAX; + desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + DX::ThrowIfFailed(device->CreateSamplerState(&desc, m_pSamplerMirror.ReleaseAndGetAddressOf())); + } + + // Determine the aspect ratio + float fAspectRatio = 1920.0f / 1080.0f; + + // Set the transform matrices + static const XMVECTORF32 c_vEyePt = { 0.0f, 0.0f, -5.0f, 0.0f }; + static const XMVECTORF32 c_vLookatPt = { 0.0f, 0.0f, 0.0f, 0.0f }; + static const XMVECTORF32 c_vUpVec = { 0.0f, 1.0f, 0.0f, 0.0f }; + + m_matView = XMMatrixLookAtLH(c_vEyePt, c_vLookatPt, c_vUpVec); + m_matProj = XMMatrixPerspectiveFovLH(XM_PI / 3, fAspectRatio, 1.0f, 10000.0f); + +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + if (m_frontPanelControl) + { + // Create a shader resource view for the main render target + auto device = m_deviceResources->GetD3DDevice(); + DX::ThrowIfFailed(device->CreateShaderResourceView(m_deviceResources->GetRenderTarget(), nullptr, m_mainRenderTargetSRV.GetAddressOf())); + } +} +#pragma endregion + +void Sample::SetWaterColor(float red, float green, float blue) +{ + m_waterColor[0] = red; + m_waterColor[1] = green; + m_waterColor[2] = blue; + m_waterColor[3] = 1.0f; +} + +void Sample::DrawDolphin(Dolphin &dolphin) +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + context->Map(m_VSConstantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + { + VS_CONSTANT_BUFFER* vertShaderConstData = (VS_CONSTANT_BUFFER*)mappedResource.pData; + + vertShaderConstData->vZero = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); + vertShaderConstData->vConstants = XMVectorSet(1.0f, 0.5f, 0.2f, 0.05f); + + FLOAT fBlendWeight = dolphin.GetBlendWeight(); + FLOAT fWeight1; + FLOAT fWeight2; + FLOAT fWeight3; + + if (fBlendWeight > 0.0f) + { + fWeight1 = fabsf(fBlendWeight); + fWeight2 = 1.0f - fabsf(fBlendWeight); + fWeight3 = 0.0f; + } + else + { + fWeight1 = 0.0f; + fWeight2 = 1.0f - fabsf(fBlendWeight); + fWeight3 = fabsf(fBlendWeight); + } + vertShaderConstData->vWeight = XMVectorSet(fWeight1, fWeight2, fWeight3, 0.0f); + + // Lighting vectors (in world space and in dolphin model space) + // and other constants + vertShaderConstData->vLight = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vLightDolphinSpace = XMVectorSet(0.00f, 1.00f, 0.00f, 0.00f); + vertShaderConstData->vDiffuse = XMVectorSet(1.00f, 1.00f, 1.00f, 1.00f); + vertShaderConstData->vAmbient = XMVectorSet(m_ambient[0], m_ambient[1], m_ambient[2], m_ambient[3]); + vertShaderConstData->vFog = XMVectorSet(0.50f, 50.00f, 1.00f / (50.0f - 1.0f), 0.00f); + + float totalSeconds = float(m_timer.GetTotalSeconds()); + vertShaderConstData->vCaustics = XMVectorSet(0.05f, 0.05f, sinf(totalSeconds) / 8, cosf(totalSeconds) / 10); + + XMVECTOR vDeterminant; + XMMATRIX matDolphin = dolphin.GetWorld(); + XMMATRIX matDolphinInv = XMMatrixInverse(&vDeterminant, matDolphin); + vertShaderConstData->vLightDolphinSpace = XMVector4Normalize(XMVector4Transform(vertShaderConstData->vLight, matDolphinInv)); + + // Vertex shader operations use transposed matrices + XMMATRIX matCamera = XMMatrixMultiply(matDolphin, m_matView); + XMMATRIX mat = XMMatrixMultiply(matCamera, m_matProj); + vertShaderConstData->matTranspose = XMMatrixTranspose(mat); + vertShaderConstData->matCameraTranspose = XMMatrixTranspose(matCamera); + vertShaderConstData->matViewTranspose = XMMatrixTranspose(m_matView); + vertShaderConstData->matProjTranspose = XMMatrixTranspose(m_matProj); + + } + context->Unmap(m_VSConstantBuffer.Get(), 0); + + context->VSSetConstantBuffers(0, 1, m_VSConstantBuffer.GetAddressOf()); + dolphin.Render(context, m_pixelShader.Get(), m_causticTextureViews[m_currentCausticTextureView].Get()); +} diff --git a/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.h b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.h new file mode 100644 index 0000000000000000000000000000000000000000..c3d95107ff2f2b24aacc795afe51dc73f9cbb0b9 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.h @@ -0,0 +1,109 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelDolphin.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "Dolphin.h" + +#include "FrontPanel\FrontPanelRenderTarget.h" +#include "FrontPanel\FrontPanelDisplay.h" +#include "FrontPanel\FrontPanelInput.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void SetWaterColor(float red, float green, float blue); + + void DrawDolphin(Dolphin &dolphin); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // DirectXTK objects + std::unique_ptr m_states; + std::unique_ptr m_fxFactory; + + // Game state + Microsoft::WRL::ComPtr m_VSConstantBuffer; + Microsoft::WRL::ComPtr m_PSConstantBuffer; + Microsoft::WRL::ComPtr m_pSamplerMirror; + + // Transform matrices + DirectX::SimpleMath::Matrix m_matView; + DirectX::SimpleMath::Matrix m_matProj; + + // array of dolphins + std::array, 4> m_dolphins; + + // Seafloor object + std::unique_ptr m_seafloor; + std::unique_ptr m_seaEffect; + Microsoft::WRL::ComPtr m_seaFloorTextureView; + Microsoft::WRL::ComPtr m_seaFloorVertexLayout; + + // Water caustics + Microsoft::WRL::ComPtr m_causticTextureViews[32]; + unsigned int m_currentCausticTextureView; + Microsoft::WRL::ComPtr m_pixelShader; + + float m_waterColor[4]; + float m_ambient[4]; + + // Front Panel Render Target + // Helper class to convert a GPU resource to grayscale and then render to the Front Panel + std::unique_ptr m_frontPanelRenderTarget; + + // Shader resource view for the whole screen + // This is the input to the FrontPanelRender target + Microsoft::WRL::ComPtr m_mainRenderTargetSRV; + + // FrontPanel objects + Microsoft::WRL::ComPtr m_frontPanelControl; + std::unique_ptr m_frontPanelDisplay; + std::unique_ptr m_frontPanelInput; + ATG::FrontPanelInput::ButtonStateTracker m_frontPanelInputButtons; +}; diff --git a/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.sln b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.sln new file mode 100644 index 0000000000000000000000000000000000000000..59e394f7a2ed8e4dd27eca14905a9ec2b3582537 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontPanelDolphin", "FrontPanelDolphin.vcxproj", "{871C13CC-5F83-41DE-8003-E9AFBB6A6533}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Debug|Durango.ActiveCfg = Debug|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Debug|Durango.Build.0 = Debug|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Debug|Durango.Deploy.0 = Debug|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Profile|Durango.ActiveCfg = Profile|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Profile|Durango.Build.0 = Profile|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Profile|Durango.Deploy.0 = Profile|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Release|Durango.ActiveCfg = Release|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Release|Durango.Build.0 = Release|Durango + {871C13CC-5F83-41DE-8003-E9AFBB6A6533}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.vcxproj b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..f33dbd284949c1c5c86cdc584029c32804430150 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.vcxproj @@ -0,0 +1,304 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + FrontPanelDolphin + {871c13cc-5f83-41de-8003-e9afbb6a6533} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + xboxfrontpanel.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + + ShadeCausticsPixel + ShadeCausticsPixel + ShadeCausticsPixel + Pixel + Pixel + Pixel + + + ShadeDolphinVertex + ShadeDolphinVertex + ShadeDolphinVertex + Vertex + Vertex + Vertex + + + ShadeSeaFloorVertex + ShadeSeaFloorVertex + ShadeSeaFloorVertex + Vertex + Vertex + Vertex + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.vcxproj.filters b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..0519d65eef810813850dc7f36fd0342114151f70 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/FrontPanelDolphin.vcxproj.filters @@ -0,0 +1,240 @@ + + + + + 5c33eca8-6f5b-4cb7-8c1d-a257f87e461f + + + 014fff94-b26d-48c8-bd37-17ea463598ea + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {efb1994c-8975-4efc-9c44-2f6eccff391a} + + + {adebea98-df7f-4838-a09b-03a5af36a79b} + + + {f6731496-b217-488f-a3b5-8a7aad932f79} + + + {8bff1eac-0bdb-40be-baaf-bf29b7da389b} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + Assets\textures + + + + + Shaders + + + Shaders + + + Assets\mesh + + + Assets\mesh + + + Assets\mesh + + + Assets\mesh + + + + + + Shaders + + + Shaders + + + Shaders + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDolphin/Main.cpp b/XDKSamples/System/FrontPanelDolphin/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39da9b2bd84bb1c71e37daa94c87050ab0e4f211 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelDolphin.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDolphin/Package.appxmanifest b/XDKSamples/System/FrontPanelDolphin/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..59cbda6edb4b4e3c320de36fd20e7e185bc225b7 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + FrontPanelDolphin + Xbox Advanced Technology Group + Assets\StoreLogo.png + FrontPanelDolphin + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/FrontPanelDolphin/PixelShaders.hlsli b/XDKSamples/System/FrontPanelDolphin/PixelShaders.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..90c50371e13f4f4321efd68eec1beb19da2bda23 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/PixelShaders.hlsli @@ -0,0 +1,58 @@ +//-------------------------------------------------------------------------------------- +// PixelShaders.hlsli +// +// Pixel Shaders for the Dolphin sample +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +struct VSOUT +{ + float4 vPosition : SV_POSITION; + float4 vLightAndFog : COLOR0_center; // COLOR0.x = light, COLOR0.y = fog + float4 vTexCoords : TEXCOORD1; // TEXCOORD0.xy = basetex, TEXCOORD0.zw = caustictex +}; + +//-------------------------------------------------------------------------------------- +// Pixel shader constants +//-------------------------------------------------------------------------------------- +sampler SamplerSkin; +sampler SamplerCaustics; + +cbuffer cb0 +{ + uniform float3 g_vAmbient : register(c0); // Material ambient color + uniform float4 g_vFogColor : register(c1); // Fog color +} + +Texture2D TextureSkin; +Texture2D TextureCaustics; + +//-------------------------------------------------------------------------------------- +// Name: ShadeCausticsPixel() +// Desc: Pixel shader to add underwater caustics to a lit base texture. +//-------------------------------------------------------------------------------------- +float4 ShadeCausticsPixel(VSOUT Input) : SV_Target +{ + + // Decompress input values + float3 vLightColor = Input.vLightAndFog.xxx; + float fFogValue = Input.vLightAndFog.y; + float2 vBaseTexCoords = Input.vTexCoords.xy; + float2 vCausticTexCoords = Input.vTexCoords.zw; + + // Combine lighting, base texture and water caustics texture + float4 vDiffuse = TextureSkin.Sample(SamplerSkin, vBaseTexCoords); + float4 vCaustics = TextureCaustics.Sample(SamplerCaustics, vCausticTexCoords); + + // Combine lighting, base texture and water caustics texture + float4 PixelColor0 = vDiffuse * float4(vLightColor + g_vAmbient, 1); + float4 PixelColor1 = vCaustics * float4(vLightColor, 1); + + // Return color blended with fog + return lerp(g_vFogColor, PixelColor0 + PixelColor1, fFogValue); + + +} + + diff --git a/XDKSamples/System/FrontPanelDolphin/SeaFloorVS.hlsl b/XDKSamples/System/FrontPanelDolphin/SeaFloorVS.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..5d3f396188fc386b9e3430be17c0db79e5f16d9e --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/SeaFloorVS.hlsl @@ -0,0 +1 @@ +#include "VertexShaders.hlsli" diff --git a/XDKSamples/System/FrontPanelDolphin/StepTimer.h b/XDKSamples/System/FrontPanelDolphin/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/FrontPanelDolphin/Telemetry.h b/XDKSamples/System/FrontPanelDolphin/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/FrontPanelDolphin/VertexShaders.hlsli b/XDKSamples/System/FrontPanelDolphin/VertexShaders.hlsli new file mode 100644 index 0000000000000000000000000000000000000000..799be3bc40e17944272883a9a1b56b089a98e12e --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/VertexShaders.hlsli @@ -0,0 +1,123 @@ +//-------------------------------------------------------------------------------------- +// VertexShaders.hlsli +// +// Vertex Shaders for the Dolphin sample +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +struct VSOUT +{ + float4 vPosition : SV_POSITION; + float4 vLightAndFog : COLOR0_center; // COLOR0.x = light, COLOR0.y = fog + float4 vTexCoords : TEXCOORD1; // TEXCOORD0.xy = basetex, TEXCOORD0.zw = caustictex +}; + + +//-------------------------------------------------------------------------------------- +// Vertex shader constants +//-------------------------------------------------------------------------------------- + +cbuffer cb0 +{ + uniform float4 g_vZero : register(c0); // ( 0, 0, 0, 0 ) + uniform float4 g_vConstants : register(c1); // ( 1, 0.5, -, - ) + uniform float3 g_vBlendWeights : register(c2); // ( fWeight1, fWeight2, fWeight3, 0 ) + uniform float4x4 g_matWorldViewProj : register(c4); // world-view-projection matrix + uniform float4x4 g_matWorldView : register(c8); // world-view matrix + uniform float4x4 g_matView : register(c12); // view matrix + uniform float4x4 g_matProjection : register(c16); // projection matrix + uniform float3 g_vSeafloorLightDir : register(c20); // seafloor light direction + uniform float3 g_vDolphinLightDir : register(c21); // dolphin light direction + uniform float4 g_vDiffuse : register(c23); + uniform float4 g_vAmbient : register(c24); + uniform float4 g_vFogRange : register(c22); // ( x, fog_end, (1/(fog_end-fog_start)), x) + uniform float4 g_vTexGen : register(c25); +} + +//-------------------------------------------------------------------------------------- +// Name: ShadeSeaFloorVertex() +// Desc: Vertex shader for the seafloor +//-------------------------------------------------------------------------------------- +VSOUT ShadeSeaFloorVertex(const float3 vPosition : SV_POSITION, + const float3 vNormal : NORMAL, + const float2 vBaseTexCoords : TEXCOORD0) +{ + // Transform to view space (world matrix is identity) + float4 vViewPosition = mul(float4(vPosition, 1.0f), g_matView); + + // Transform to projection space + float4 vOutputPosition = mul(vViewPosition, g_matProjection); + + // Lighting calculation + float fLightValue = max(dot(vNormal, g_vSeafloorLightDir), g_vZero.x); + + // Generate water caustic tex coords from vertex xz position + float2 vCausticTexCoords = g_vTexGen.xx * vViewPosition.xz + g_vTexGen.zw; + + // Fog calculation: + float fFogValue = clamp((g_vFogRange.y - vViewPosition.z) * g_vFogRange.z, g_vZero.x, g_vConstants.x); + + // Compress output values + VSOUT Output; + Output.vPosition = vOutputPosition; + Output.vLightAndFog.x = fLightValue; + Output.vLightAndFog.y = fFogValue; + Output.vTexCoords.xy = 10 * vBaseTexCoords; + Output.vTexCoords.zw = vCausticTexCoords; + + Output.vLightAndFog.z = 0.0f; + Output.vLightAndFog.w = 0.0f; + + return Output; +} + + +//-------------------------------------------------------------------------------------- +// Name: ShadeDolphinVertex() +// Desc: Vertex shader for the dolphin +//-------------------------------------------------------------------------------------- +VSOUT ShadeDolphinVertex(const float3 vPosition0 : POSITION0, + const float3 vPosition1 : POSITION1, + const float3 vPosition2 : POSITION2, + const float3 vNormal0 : NORMAL0, + const float3 vNormal1 : NORMAL1, + const float3 vNormal2 : NORMAL2, + const float2 vBaseTexCoords : TEXCOORD0) +{ + // Tween the 3 positions (v0,v1,v2) into one position + float4 vModelPosition = float4(vPosition0 * g_vBlendWeights.x + vPosition1 * g_vBlendWeights.y + vPosition2 * g_vBlendWeights.z, 1.0f); + + // Transform position to the clipping space + float4 vOutputPosition = mul(vModelPosition, g_matWorldViewProj); + + // Transform position to the camera space + float4 vViewPosition = mul(vModelPosition, g_matWorldView); + + // Tween the 3 normals (v3,v4,v5) into one normal + float3 vModelNormal = vNormal0 * g_vBlendWeights.x + vNormal1 * g_vBlendWeights.y + vNormal2 * g_vBlendWeights.z; + + // Do the lighting calculation + float fLightValue = max(dot(vModelNormal, g_vDolphinLightDir), g_vZero.x); + + // Generate water caustic tex coords from vertex xz position + float2 vCausticTexCoords = g_vConstants.yy * vViewPosition.xz; + + // Fog calculation: + float fFogValue = clamp((g_vFogRange.y - vViewPosition.z) * g_vFogRange.z, g_vZero.x, g_vConstants.x); + + // Compress output values + VSOUT Output; + Output.vPosition = vOutputPosition; + Output.vLightAndFog.x = fLightValue; + Output.vLightAndFog.y = fFogValue; + Output.vTexCoords.xy = vBaseTexCoords; + Output.vTexCoords.zw = vCausticTexCoords; + + Output.vLightAndFog.z = 0.0f; + Output.vLightAndFog.w = 1.0f; + + return Output; +} + + diff --git a/XDKSamples/System/FrontPanelDolphin/pch.cpp b/XDKSamples/System/FrontPanelDolphin/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/FrontPanelDolphin/pch.h b/XDKSamples/System/FrontPanelDolphin/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..ab0ca50063b2f9408c3dcc084e4197a73098efdc --- /dev/null +++ b/XDKSamples/System/FrontPanelDolphin/pch.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This sample requires the March 2017 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "CommonStates.h" +#include "Effects.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Model.h" +#include "SimpleMath.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelDolphin/readme.docx b/XDKSamples/System/FrontPanelDolphin/readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..c489d6ef9f4630e14b1c17ad21335a081e3268ee Binary files /dev/null and b/XDKSamples/System/FrontPanelDolphin/readme.docx differ diff --git a/XDKSamples/System/FrontPanelGame/Assets/Logo.png b/XDKSamples/System/FrontPanelGame/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/Assets/Logo.png differ diff --git a/XDKSamples/System/FrontPanelGame/Assets/LucidaConsole12.rasterfont b/XDKSamples/System/FrontPanelGame/Assets/LucidaConsole12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..8499b85c5f12d1745e3ab17bd357d9ea3a2600ad Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/Assets/LucidaConsole12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelGame/Assets/SmallLogo.png b/XDKSamples/System/FrontPanelGame/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/FrontPanelGame/Assets/SplashScreen.png b/XDKSamples/System/FrontPanelGame/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/FrontPanelGame/Assets/StoreLogo.png b/XDKSamples/System/FrontPanelGame/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/FrontPanelGame/Assets/WideLogo.png b/XDKSamples/System/FrontPanelGame/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/Assets/WideLogo.png differ diff --git a/XDKSamples/System/FrontPanelGame/DeviceResources.cpp b/XDKSamples/System/FrontPanelGame/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29759abd16cd8674d19a6bdb3f66507f0e0990ea --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/DeviceResources.cpp @@ -0,0 +1,325 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_renderTarget->SetName(L"Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + } + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + + if (m_d3dGameDVRRenderTarget) + { + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + } + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/FrontPanelGame/DeviceResources.h b/XDKSamples/System/FrontPanelGame/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..1edd14523e9006c77bca692edc98d8732d1b0e67 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/DeviceResources.h @@ -0,0 +1,84 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + static const unsigned int c_EnableHDR = 0x4; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelGame/FrontPanelGame.cpp b/XDKSamples/System/FrontPanelGame/FrontPanelGame.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e25cf858b801f7e915461b8ef3fdf24e10d26c24 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/FrontPanelGame.cpp @@ -0,0 +1,343 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelGame.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelGame.h" + +#include "ATGColors.h" + +#include "FrontPanel\CPUShapes.h" + +extern void ExitSample(); + +using namespace DirectX; +using namespace ATG; +using ButtonState = FrontPanelInput::ButtonStateTracker::ButtonState; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() + : m_frame(0) + , m_score(0) + , m_alive(false) +{ + // Renders only 2D, so no need for a depth buffer. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + // Check to see whethter there is a front panel + if (IsXboxFrontPanelAvailable()) + { + // Get the default front panel + DX::ThrowIfFailed(GetDefaultXboxFrontPanel(m_frontPanelControl.ReleaseAndGetAddressOf())); + + // Initialize the FrontPanelDisplay object + m_frontPanelDisplay = std::make_unique(m_frontPanelControl.Get()); + + // Initialize the FrontPanelInput object + m_frontPanelInput = std::make_unique(m_frontPanelControl.Get()); + } +} + +void Sample::InitializeGame(bool alive) +{ + m_alive = alive; + + m_score = 0; + + m_gameBoard = std::make_shared(*m_frontPanelDisplay.get()); + + if (m_alive) + { + m_snake = std::make_shared( + m_gameBoard, + 0, 1, + 5, 5); + + m_gameBoard->SpawnFood(); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + // Using fixed frame rate with 60fps target frame rate + m_timer.SetFixedTimeStep(true); + m_timer.SetTargetElapsedSeconds(1.0 / 60.0); + + // Don't do anything if there is no front panel + if (m_frontPanelControl) + { + m_font = RasterFont(L"assets\\LucidaConsole12.rasterfont"); + + InitializeGame(false); + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + // Don't do anything if there is no front panel + if (m_frontPanelControl) + { + UpdateGame(); + + RenderToFrontPanel(); + } + + PIXEndEvent(); +} + +void Sample::RenderToFrontPanel() const +{ + m_frontPanelDisplay->Clear(); + + BufferDesc fpDesc = m_frontPanelDisplay->GetBufferDescriptor(); + m_font.DrawStringFmt(fpDesc, 0, 0, L"\nSnake\n\nScore: %u", m_score); + + unsigned int ts = static_cast(m_timer.GetTotalSeconds()); + + CPUShapes shapes = CPUShapes(m_frontPanelDisplay->GetDisplayWidth(), m_frontPanelDisplay->GetDisplayHeight(), m_frontPanelDisplay->GetBuffer()); + shapes.RenderRect(0 + ts % 11, 0, 2, 2); + + m_gameBoard->Render(); + + m_frontPanelDisplay->Present(); +} + +void Sample::UpdateGame() +{ + RespondToInput(); + + // Each frame is 1/60th of a second + static unsigned frames = 0; + + // advancing the simulation every 8 frames seems to the right amount + // given the size of the dpad control etc. + if (m_alive && (frames > 8)) + { + switch (m_snake->Move()) + { + case SnakeMoveResult::Move: + break; + + case SnakeMoveResult::Eat: + m_gameBoard->SpawnFood(); + m_score++; + break; + + case SnakeMoveResult::Fail: + m_alive = false; + break; + } + + frames = 0; + } + else if (!m_alive && (frames > 20)) + { + // Blink the light around the start button + auto state = m_frontPanelInput->GetState(); + auto lights = state.lights.rawLights; + + if (state.lights.light1) + { + lights &= ~XBOX_FRONT_PANEL_LIGHTS_LIGHT1; + } + else + { + lights |= XBOX_FRONT_PANEL_LIGHTS_LIGHT1; + } + m_frontPanelInput->SetLightStates(static_cast(lights)); + + frames = 0; + } + + ++frames; +} + +void Sample::RespondToInput() +{ + + auto fpInput = m_frontPanelInput->GetState(); + m_frontPanelInputButtons.Update(fpInput); + + if(m_snake && m_frontPanelInputButtons.dpadUp == ButtonState::PRESSED) + { + m_snake->SetDirection(0, -1); + } + else if (m_snake && m_frontPanelInputButtons.dpadDown == ButtonState::PRESSED) + { + m_snake->SetDirection(0, 1); + } + else if(m_snake && m_frontPanelInputButtons.dpadLeft == ButtonState::PRESSED) + { + m_snake->SetDirection(-1, 0); + } + else if(m_snake && m_frontPanelInputButtons.dpadRight == ButtonState::PRESSED) + { + m_snake->SetDirection(1, 0); + } + else if(m_frontPanelInputButtons.button1 == ButtonState::PRESSED) + { + InitializeGame(true); + } + + // Use the select button to take a screen capture + if (m_frontPanelInputButtons.buttonSelect == ButtonState::PRESSED) + { + m_frontPanelDisplay->SaveDDSToFile(L"D:\\FrontPanelDisplay.dds"); + } + + if (m_frontPanelInputButtons.buttonsChanged) + { + XBOX_FRONT_PANEL_LIGHTS lights = XBOX_FRONT_PANEL_LIGHTS_NONE; + + if(m_frontPanelInputButtons.button1 & ButtonState::HELD) + { + lights = static_cast(lights | XBOX_FRONT_PANEL_LIGHTS_LIGHT1); + } + if (m_frontPanelInputButtons.button2 & ButtonState::HELD) + { + lights = static_cast(lights | XBOX_FRONT_PANEL_LIGHTS_LIGHT2); + } + if (m_frontPanelInputButtons.button3 & ButtonState::HELD) + { + lights = static_cast(lights | XBOX_FRONT_PANEL_LIGHTS_LIGHT3); + } + if (m_frontPanelInputButtons.button4 & ButtonState::HELD) + { + lights = static_cast(lights | XBOX_FRONT_PANEL_LIGHTS_LIGHT4); + } + if (m_frontPanelInputButtons.button5 & ButtonState::HELD) + { + lights = static_cast(lights | XBOX_FRONT_PANEL_LIGHTS_LIGHT5); + } + + m_frontPanelInput->SetLightStates(lights); + } +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto output = m_deviceResources->GetOutputSize(); + + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(output.right, output.bottom); + + m_batch->Begin(); + m_batch->Draw(m_background.Get(), output); + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + m_batch = std::make_unique(context); + + DX::ThrowIfFailed( + CreateWICTextureFromFile(device, + IsXboxFrontPanelAvailable() ? L"FrontPanelPresent.png" : L"NoFrontPanel.png", + nullptr, m_background.ReleaseAndGetAddressOf()) + ); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/FrontPanelGame/FrontPanelGame.h b/XDKSamples/System/FrontPanelGame/FrontPanelGame.h new file mode 100644 index 0000000000000000000000000000000000000000..56d1468cce33da34c1139360a8e8ca4bf9ead3fd --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/FrontPanelGame.h @@ -0,0 +1,74 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelGame.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + +#include "Game.h" + +#include "FrontPanel/FrontPanelInput.h" +#include "FrontPanel/RasterFont.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void InitializeGame(bool alive); + void RenderToFrontPanel() const; + void UpdateGame(); + void RespondToInput(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_batch; + Microsoft::WRL::ComPtr m_background; + // FrontPanel objects. + Microsoft::WRL::ComPtr m_frontPanelControl; + std::unique_ptr m_frontPanelDisplay; + std::unique_ptr m_frontPanelInput; + ATG::FrontPanelInput::ButtonStateTracker m_frontPanelInputButtons; + ATG::RasterFont m_font; + + // Game objects + unsigned int m_score; + bool m_alive; + std::shared_ptr m_gameBoard; + std::shared_ptr m_snake; + +}; diff --git a/XDKSamples/System/FrontPanelGame/FrontPanelGame.sln b/XDKSamples/System/FrontPanelGame/FrontPanelGame.sln new file mode 100644 index 0000000000000000000000000000000000000000..43fb0352d92d1a85879970ff15e655f2bfc9f3e7 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/FrontPanelGame.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontPanelGame", "FrontPanelGame.vcxproj", "{5C1C7516-8637-4E05-B5ED-89CE356AA837}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Debug|Durango.ActiveCfg = Debug|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Debug|Durango.Build.0 = Debug|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Debug|Durango.Deploy.0 = Debug|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Profile|Durango.ActiveCfg = Profile|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Profile|Durango.Build.0 = Profile|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Profile|Durango.Deploy.0 = Profile|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Release|Durango.ActiveCfg = Release|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Release|Durango.Build.0 = Release|Durango + {5C1C7516-8637-4E05-B5ED-89CE356AA837}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/FrontPanelGame/FrontPanelGame.vcxproj b/XDKSamples/System/FrontPanelGame/FrontPanelGame.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..ada28861da05149792c42b512514bc084e382d70 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/FrontPanelGame.vcxproj @@ -0,0 +1,230 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + FrontPanelGame + {5c1c7516-8637-4e05-b5ed-89ce356aa837} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + xboxfrontpanel.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelGame/FrontPanelGame.vcxproj.filters b/XDKSamples/System/FrontPanelGame/FrontPanelGame.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..798af3d9a7a6bc54a8b1fb771a1baffc4091f238 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/FrontPanelGame.vcxproj.filters @@ -0,0 +1,112 @@ + + + + + 4c6ed9a7-243d-4747-962c-226b99b6c79b + + + c51bfa2c-165b-4923-b3c0-0fbb47bd1e5a + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {86f8f69d-1925-416e-a173-bc0f81288f3b} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelGame/Game.cpp b/XDKSamples/System/FrontPanelGame/Game.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c2af62c086f5e5f7cbf90153cd28f33523e1032 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/Game.cpp @@ -0,0 +1,190 @@ +//-------------------------------------------------------------------------------------- +// Game.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "Game.h" + +#include "FrontPanel\CPUShapes.h" + +using namespace ATG; + +namespace +{ + int RandInt(int low, int high) + { + return (rand() % (high - low + 1)) + low; + } +} // ANONYMOUS namespace + +GameBoard::GameBoard(FrontPanelDisplay &display) + : frontPanelDisplay(display) +{ + blankDots.reserve(GAME_BOARD_WIDTH * GAME_BOARD_HEIGHT); + + for (int x = 0; x < GAME_BOARD_WIDTH; x++) + { + for (int y = 0; y < GAME_BOARD_HEIGHT; y++) + { + auto newDot = std::make_shared(x, y); + + gameBoard[x][y] = newDot; + + blankDots.push_back(newDot); + } + } +} + +void GameBoard::Render() const +{ + + CPUShapes shapes = CPUShapes(frontPanelDisplay.GetDisplayWidth(), frontPanelDisplay.GetDisplayHeight(), frontPanelDisplay.GetBuffer()); + for (int x = 0; x < GAME_BOARD_WIDTH; x++) + { + for (int y = 0; y < GAME_BOARD_HEIGHT; y++) + { + if (gameBoard[x][y]->State != DotState::Empty) + { + shapes.RenderRect( + GAME_BOARD_LEFT + GAME_BOARD_DOT_SIZE * x, + GAME_BOARD_TOP + GAME_BOARD_DOT_SIZE * y, + GAME_BOARD_DOT_SIZE, GAME_BOARD_DOT_SIZE); + } + } + } + + shapes.RenderRect( + GAME_BOARD_OUTLINE_LEFT, + GAME_BOARD_OUTLINE_TOP, + GAME_BOARD_OUTLINE_WIDTH, + GAME_BOARD_OUTLINE_HEIGHT, + 0x77, + false); +} + +void GameBoard::SpawnFood() +{ + if (blankDots.size() > 0) + { + int index = RandInt(0, (int)blankDots.size() - 1); + + SetDotState(blankDots[index], DotState::Food); + } +} + +void GameBoard::SetDotState(std::shared_ptr dot, DotState state) +{ + if (state == dot->State) + { + return; + } + else if (dot->State == DotState::Empty && state != DotState::Empty) + { + for (unsigned int i = 0; i < blankDots.size(); i++) + { + if (dot == blankDots[i]) + { + blankDots[i] = blankDots[blankDots.size() - 1]; + + blankDots.pop_back(); + + break; + } + } + } + else if (dot->State != DotState::Empty && state == DotState::Empty) + { + blankDots.push_back(dot); + } + + dot->State = state; +} + +std::shared_ptr GameBoard::GetDot(int x, int y) +{ + if (x < 0 || x >= GAME_BOARD_WIDTH + || y < 0 || y >= GAME_BOARD_HEIGHT) + { + return nullptr; + } + else + { + return gameBoard[x][y]; + } +} + +Snake::Snake( + std::shared_ptr board, + int directionX, + int directionY, + int startX, + int startY) + : DirectionX(0) + , DirectionY(0) + , BackwardsDirectionX(0) + , BackwardsDirectionY(0) +{ + gameBoard = board; + + DirectionX = directionX; + DirectionY = directionY; + + BackwardsDirectionX = -DirectionX; + BackwardsDirectionY = -DirectionY; + + Body.push_front(gameBoard->GetDot(startX, startY)); +} + +void Snake::SetDirection(int x, int y) +{ + if (BackwardsDirectionX != x || BackwardsDirectionY != y) + { + DirectionX = x; + DirectionY = y; + } +} + +SnakeMoveResult Snake::Move() +{ + auto head = Body.front(); + + auto next = gameBoard->GetDot(head->X + DirectionX, head->Y + DirectionY); + + BackwardsDirectionX = -DirectionX; + BackwardsDirectionY = -DirectionY; + + if (next == nullptr) + { + return SnakeMoveResult::Fail; + } + + switch (next->State) + { + case DotState::Empty: + + gameBoard->SetDotState(next, DotState::Filled); + + Body.push_front(next); + + gameBoard->SetDotState(Body.back(), DotState::Empty); + + Body.pop_back(); + + return SnakeMoveResult::Move; + + case DotState::Food: + + gameBoard->SetDotState(next, DotState::Filled); + + Body.push_front(next); + + return SnakeMoveResult::Eat; + + case DotState::Filled: + default: + + return SnakeMoveResult::Fail; + } +} diff --git a/XDKSamples/System/FrontPanelGame/Game.h b/XDKSamples/System/FrontPanelGame/Game.h new file mode 100644 index 0000000000000000000000000000000000000000..6b09c4a3c0bbc6e402ea39490315c5e449fa7842 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/Game.h @@ -0,0 +1,101 @@ +//-------------------------------------------------------------------------------------- +// Game.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "FrontPanel\FrontPanelDisplay.h" + +enum DotState +{ + Empty, + Food, + Filled, +}; + +struct Dot +{ + Dot(int x, int y) + : State(DotState::Empty) + , X(x) + , Y(y) + {}; + + DotState State; + int X; + int Y; +}; + +class GameBoard +{ +public: + + GameBoard(ATG::FrontPanelDisplay &display); + + void Render() const; + + void SpawnFood(); + + void SetDotState(std::shared_ptr dot, DotState state); + + std::shared_ptr GetDot(int x, int y); + +private: + + static const int GAME_BOARD_LEFT = 256 / 4 + 2; + static const int GAME_BOARD_TOP = 2; + + static const int GAME_BOARD_DOT_SIZE = 4; + + static const int GAME_BOARD_WIDTH = (254 - GAME_BOARD_LEFT) / GAME_BOARD_DOT_SIZE; + static const int GAME_BOARD_HEIGHT = (62 - GAME_BOARD_TOP) / GAME_BOARD_DOT_SIZE; + + static const int GAME_BOARD_OUTLINE_LEFT = GAME_BOARD_LEFT - 1; + static const int GAME_BOARD_OUTLINE_TOP = GAME_BOARD_TOP - 1; + + static const int GAME_BOARD_OUTLINE_WIDTH = GAME_BOARD_WIDTH * GAME_BOARD_DOT_SIZE + 2; + static const int GAME_BOARD_OUTLINE_HEIGHT = GAME_BOARD_HEIGHT * GAME_BOARD_DOT_SIZE + 2; + + ATG::FrontPanelDisplay &frontPanelDisplay; + + std::vector> blankDots; + + std::shared_ptr gameBoard[GAME_BOARD_WIDTH][GAME_BOARD_HEIGHT]; +}; + +enum SnakeMoveResult +{ + Move, + Fail, + Eat, +}; + +class Snake +{ +public: + + Snake( + std::shared_ptr board, + int directionX, + int directionY, + int startX, + int startY); + + void SetDirection(int x, int y); + + SnakeMoveResult Move(); + +private: + + std::shared_ptr gameBoard; + + std::list> Body; + int DirectionX; + int DirectionY; + + int BackwardsDirectionX; + int BackwardsDirectionY; +}; + diff --git a/XDKSamples/System/FrontPanelGame/Main.cpp b/XDKSamples/System/FrontPanelGame/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0bc8ddfe3f8013aec132709e9b653caa647b6ca1 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelGame.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelGame/Package.appxmanifest b/XDKSamples/System/FrontPanelGame/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..12b165d3976406aeb24951f6c7aeb2099856b2a8 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + FrontPanelGame + Xbox Advanced Technology Group + Assets\StoreLogo.png + FrontPanelGame + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/FrontPanelGame/StepTimer.h b/XDKSamples/System/FrontPanelGame/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/FrontPanelGame/Telemetry.h b/XDKSamples/System/FrontPanelGame/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/FrontPanelGame/pch.cpp b/XDKSamples/System/FrontPanelGame/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/FrontPanelGame/pch.h b/XDKSamples/System/FrontPanelGame/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..fb2e746ff4242091584ab63922fa8fa4e8afe04b --- /dev/null +++ b/XDKSamples/System/FrontPanelGame/pch.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This sample requires the March 2017 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "WICTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelGame/readme.docx b/XDKSamples/System/FrontPanelGame/readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..a374ecd16a8f41749e67538590711371404b8a19 Binary files /dev/null and b/XDKSamples/System/FrontPanelGame/readme.docx differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBlack12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBlack12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..5533f78f3439bf23c9b839572857c21c0520bf94 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBlack12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBlack16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBlack16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..95c2b4ed5be484aa5cf66498562020699ee67489 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBlack16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBlack32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBlack32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..29446e16df1c090b893436ffe7da9763ebd78248 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBlack32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBlack64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBlack64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..dd004e6937d6448c81f683d6f1d1acc1e3613969 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBlack64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBold12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBold12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..1264d96845b2a66881062d13b19f0151120dbcf8 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBold12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBold16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBold16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..f886260643d95769536dc8b5c88e056bdd96d9f6 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBold16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBold32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBold32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..b733cb9eae0f3d119900a1135e11dbd08e180651 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBold32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/ArialBold64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/ArialBold64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..f03decf0de8f77d022c053916cb75ba656b139ad Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/ArialBold64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Consolas12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Consolas12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..e372a51e8847f52bc9a9a88791ac474afc9be0c0 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Consolas12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Consolas16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Consolas16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..57ff4e93a7e9171efec7d191949c6d355ced7b49 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Consolas16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Consolas32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Consolas32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..6c3b149ebb43d7c031244507ca8bf5823daff952 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Consolas32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Consolas64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Consolas64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..9b75b9f0e62b60d4bdb26a0ab620fb03482148dd Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Consolas64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Courier12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Courier12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..db324c1f2a09e19e6349255f96eb8893b1cc9dc6 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Courier12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Courier16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Courier16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..01f937c0f6daa647c38bfc39e6e8b86f64a7939d Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Courier16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Courier32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Courier32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..7c391b92b9668708e804e011a7e86d5625981855 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Courier32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Courier64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Courier64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..ece72c5401c89a08b5dd5bdd7eab8a24ab20302f Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Courier64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Logo.png b/XDKSamples/System/FrontPanelText/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c0fc7df8cd1c677853b40c147a5a57a0e733cea6 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Logo.png differ diff --git a/XDKSamples/System/FrontPanelText/Assets/LucidaConsole12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..8499b85c5f12d1745e3ab17bd357d9ea3a2600ad Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/LucidaConsole16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..5b5bd81e9d36b7ec8012d57f08cd9bba50b4d8ac Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/LucidaConsole32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..d2521ed34d4eda7b7edf24929721f2f159035645 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/LucidaConsole64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..9effd449c645225f0c58779b735ba6578c7f99f8 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/LucidaConsole64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/MSSansSerif12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..5900cfe6162c9dac5d7bb998d45177b24fbb5f5b Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/MSSansSerif16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..6ae89ac8074384f6a6ddab42b9a71e84a4e327b4 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/MSSansSerif32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..b426bcb288030c65450f194ad6dd213dadd42c45 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/MSSansSerif64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..a8136d3a95c5a95c4904feceb4d53acaf5e3b568 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/MSSansSerif64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/SegoeUI12.rasterfont b/XDKSamples/System/FrontPanelText/Assets/SegoeUI12.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..462fc91aeee4f10d581d1d269079deea7fc047d3 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/SegoeUI12.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/SegoeUI16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/SegoeUI16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..f062aa1ef69373bb3102b81f03f05eadca2da511 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/SegoeUI16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/SegoeUI32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/SegoeUI32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..cf93ddc671b5b599fa56502c2804f7ab4bcbfbf4 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/SegoeUI32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/SegoeUI64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/SegoeUI64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..19dfc9fd1672c7b2bffb76b589a7c476227f6254 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/SegoeUI64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/SmallLogo.png b/XDKSamples/System/FrontPanelText/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c352cc68fce5c0410210abbe08188ef1159ec0d2 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/FrontPanelText/Assets/SplashScreen.png b/XDKSamples/System/FrontPanelText/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..96fede95bd502a1bb17ca64976c397455711f69a Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/FrontPanelText/Assets/StoreLogo.png b/XDKSamples/System/FrontPanelText/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/FrontPanelText/Assets/WideLogo.png b/XDKSamples/System/FrontPanelText/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..02ba097439184f85fe04530259c8dab9dc303988 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/WideLogo.png differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Xbox16.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Xbox16.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..693dea026ce0155a89074a94952e066b9f45b38f Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Xbox16.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Xbox18.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Xbox18.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..5d05da6e5de289b797a342ce39212aff9169d4de Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Xbox18.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Xbox24.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Xbox24.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..9d4b313d441c69b31b139183e68b65fc700ef034 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Xbox24.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Xbox32.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Xbox32.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..7ead5be180118f6060217cf1e2301150abce6938 Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Xbox32.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/Assets/Xbox64.rasterfont b/XDKSamples/System/FrontPanelText/Assets/Xbox64.rasterfont new file mode 100644 index 0000000000000000000000000000000000000000..f79a7c84846063e2ea0cb9c40fb9ee2510958cca Binary files /dev/null and b/XDKSamples/System/FrontPanelText/Assets/Xbox64.rasterfont differ diff --git a/XDKSamples/System/FrontPanelText/DeviceResources.cpp b/XDKSamples/System/FrontPanelText/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29759abd16cd8674d19a6bdb3f66507f0e0990ea --- /dev/null +++ b/XDKSamples/System/FrontPanelText/DeviceResources.cpp @@ -0,0 +1,325 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_renderTarget->SetName(L"Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + } + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + + if (m_d3dGameDVRRenderTarget) + { + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + } + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/FrontPanelText/DeviceResources.h b/XDKSamples/System/FrontPanelText/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..1edd14523e9006c77bca692edc98d8732d1b0e67 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/DeviceResources.h @@ -0,0 +1,84 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + static const unsigned int c_EnableHDR = 0x4; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelText/FrontPanelText.cpp b/XDKSamples/System/FrontPanelText/FrontPanelText.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ca2d7d8067321bed2da1c7ad0fe0d1dce5e3416 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/FrontPanelText.cpp @@ -0,0 +1,344 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelText.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelText.h" + +#include "ATGColors.h" + +namespace +{ + const wchar_t *g_fontNames[] = { + L"Courier", + L"LucidaConsole", + L"SegoeUI", + L"ArialBlack", + L"ArialBold", + L"Consolas", + L"MSSansSerif", + L"Xbox" + }; + + unsigned FindIndexForName(const wchar_t *name) + { + unsigned i = 0; + for (; i < _countof(g_fontNames); ++i) + { + if (wcscmp(name, g_fontNames[i]) == 0) + return i; + } + return i; + } + + const unsigned g_fontSizes[] = { 12, 16, 18, 24, 32, 64 }; + + bool FileExists(const wchar_t *fileName) + { + uint32_t attrs = ::GetFileAttributesW(fileName); + + return (attrs != INVALID_FILE_ATTRIBUTES + && !(attrs & FILE_ATTRIBUTE_DIRECTORY)); + } +} // ANONYMOUS namespace + +extern void ExitSample(); + +using namespace DirectX; +using namespace ATG; +using ButtonState = FrontPanelInput::ButtonStateTracker::ButtonState; +using Microsoft::WRL::ComPtr; + + +Sample::Sample() + : m_frame(0) + , m_currentEntry(0) + , m_dirty(true) +{ + // Renders only 2D, so no need for a depth buffer. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + if (IsXboxFrontPanelAvailable()) + { + // Get the default front panel + DX::ThrowIfFailed(GetDefaultXboxFrontPanel(m_frontPanelControl.ReleaseAndGetAddressOf())); + + // Initialize the FrontPanelDisplay object + m_frontPanelDisplay = std::make_unique(m_frontPanelControl.Get()); + + // Intiailize the FrontPanelInput object + m_frontPanelInput = std::make_unique(m_frontPanelControl.Get()); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + // Create all the fonts + { + wchar_t buf[MAX_PATH]; + wchar_t fontName[64]; + + for (int f = 0; f < _countof(g_fontNames); ++f) + { + for (int s = 0; s < _countof(g_fontSizes); ++s) + { + swprintf_s(fontName, L"%s%i", g_fontNames[f], g_fontSizes[s]); + swprintf_s(buf, L"Assets\\%s.rasterfont", fontName); + + if (FileExists(buf)) + { + size_t size = m_fontEntries.size(); + m_fontEntries.emplace_back(); + auto& entry = m_fontEntries[size]; + entry.size = g_fontSizes[s]; + entry.name = g_fontNames[f]; + entry.font = RasterFont(buf); + } + } + } + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_frontPanelControl) + { + auto fpInput = m_frontPanelInput->GetState(); + m_frontPanelInputButtons.Update(fpInput); + + // Change the selected font based on input from the dpad + { + + if (m_frontPanelInputButtons.dpadUp == ButtonState::PRESSED) + { + auto& entry = m_fontEntries[m_currentEntry]; + unsigned idx = FindFontEntry(entry.name, entry.size + 1); + if (idx < m_fontEntries.size()) + m_currentEntry = idx; + m_dirty = true; + } + + if (m_frontPanelInputButtons.dpadDown == ButtonState::PRESSED) + { + auto& entry = m_fontEntries[m_currentEntry]; + unsigned idx = FindFontEntry(entry.name, entry.size - 1, false); + if (idx < m_fontEntries.size()) + m_currentEntry = idx; + m_dirty = true; + } + + if (m_frontPanelInputButtons.dpadRight == ButtonState::PRESSED) + { + auto& entry = m_fontEntries[m_currentEntry]; + unsigned i = (FindIndexForName(entry.name) + 1) % _countof(g_fontNames); + unsigned idx = FindFontEntry(g_fontNames[i], entry.size); + if (idx < m_fontEntries.size()) + m_currentEntry = idx; + m_dirty = true; + } + + if (m_frontPanelInputButtons.dpadLeft == ButtonState::PRESSED) + { + auto& entry = m_fontEntries[m_currentEntry]; + unsigned i = (FindIndexForName(entry.name) + _countof(g_fontNames) - 1) % _countof(g_fontNames); + unsigned idx = FindFontEntry(g_fontNames[i], entry.size); + if (idx < m_fontEntries.size()) + m_currentEntry = idx; + m_dirty = true; + } + + if (m_frontPanelInputButtons.buttonSelect == ButtonState::PRESSED) + { + m_frontPanelDisplay->SaveDDSToFile(L"D:\\FrontPanelScreen.dds"); + } + } + + if (m_dirty) + { + // Clear the front panel display + m_frontPanelDisplay->Clear(); + + // Render text to the front panel display + BufferDesc fpDesc = m_frontPanelDisplay->GetBufferDescriptor(); + + auto &entry = m_fontEntries[m_currentEntry]; + + if (wcscmp(entry.name, L"Xbox") == 0) + { + unsigned idx = FindFontEntry(L"LucidaConsole", 12); + auto &lcEntry = m_fontEntries[idx]; + RECT r = lcEntry.font.MeasureStringFmt(L"%s%i", entry.name, entry.size); + lcEntry.font.DrawStringFmt(fpDesc, 0, 0, L"%s%i", entry.name, entry.size); + const wchar_t symbols[] = { 0xE3E3, 0xE334, 0xE37C, 0xE386, 0xE3AB, 0xE3AC, 0xE3AD, 0xE3AE, 0x0000 }; + entry.font.DrawString(fpDesc, r.right - r.left + 1, 0, symbols); + } + else + { + entry.font.DrawStringFmt(fpDesc, 0, 0, + L"%s%i\n0123456789\n" + L"abcdefghijklmnopqrstuvwxyz\n" + L"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" + L"The quick brown fox jumped over the lazy dog", + entry.name, entry.size); + } + + // Present the front pannel buffer + m_frontPanelDisplay->Present(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto output = m_deviceResources->GetOutputSize(); + + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(output.right, output.bottom); + + m_batch->Begin(); + m_batch->Draw(m_background.Get(), output); + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + m_batch = std::make_unique(context); + + DX::ThrowIfFailed( + CreateWICTextureFromFile(device, + IsXboxFrontPanelAvailable() ? L"FrontPanelPresent.png" : L"NoFrontPanel.png", + nullptr, m_background.ReleaseAndGetAddressOf()) + ); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion + +unsigned Sample::FindFontEntry(const wchar_t *name, unsigned size, bool larger) const +{ + unsigned i = 0; + unsigned prevCandidate = unsigned(m_fontEntries.size()); + + for (; i < m_fontEntries.size(); ++i) + { + const FontEntry &e = m_fontEntries[i]; + if (wcscmp(name, e.name) == 0) + { + if (e.size == size) + return i; + if (e.size > size) + return larger ? i : prevCandidate; + + prevCandidate = i; + } + else if (prevCandidate < m_fontEntries.size()) + return prevCandidate; + } + return prevCandidate; +} diff --git a/XDKSamples/System/FrontPanelText/FrontPanelText.h b/XDKSamples/System/FrontPanelText/FrontPanelText.h new file mode 100644 index 0000000000000000000000000000000000000000..52ad8eed485f3e489800b4e653966b5f40a26918 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/FrontPanelText.h @@ -0,0 +1,83 @@ +//-------------------------------------------------------------------------------------- +// FrontPanelText.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + +#include "FrontPanel/RasterFont.h" +#include "FrontPanel/FrontPanelDisplay.h" +#include "FrontPanel/FrontPanelInput.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_batch; + Microsoft::WRL::ComPtr m_background; + // RasterFonts + struct FontEntry + { + unsigned size; + const wchar_t *name; + ATG::RasterFont font; + }; + + unsigned FindFontEntry(const wchar_t *name, unsigned size, bool larger = true) const; + unsigned m_currentEntry; + std::vector m_fontEntries; + + // FrontPanel objects + Microsoft::WRL::ComPtr m_frontPanelControl; + std::unique_ptr m_frontPanelDisplay; + std::unique_ptr m_frontPanelInput; + ATG::FrontPanelInput::ButtonStateTracker m_frontPanelInputButtons; + + // It is only necessary to present to the front panel when there are changes to the pixels + // We keep track of changes to front panel pixels using m_dirty + bool m_dirty; +}; diff --git a/XDKSamples/System/FrontPanelText/FrontPanelText.sln b/XDKSamples/System/FrontPanelText/FrontPanelText.sln new file mode 100644 index 0000000000000000000000000000000000000000..a5c6535d3f50eeb06c1b940cbdaf8a37ab8fd7c5 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/FrontPanelText.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontPanelText", "FrontPanelText.vcxproj", "{BA779F69-6A9A-4241-BCF9-F31773A00FD2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Debug|Durango.ActiveCfg = Debug|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Debug|Durango.Build.0 = Debug|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Debug|Durango.Deploy.0 = Debug|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Profile|Durango.ActiveCfg = Profile|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Profile|Durango.Build.0 = Profile|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Profile|Durango.Deploy.0 = Profile|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Release|Durango.ActiveCfg = Release|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Release|Durango.Build.0 = Release|Durango + {BA779F69-6A9A-4241-BCF9-F31773A00FD2}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/FrontPanelText/FrontPanelText.vcxproj b/XDKSamples/System/FrontPanelText/FrontPanelText.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..7862cd4031d893b403552110478c2f638e9c252b --- /dev/null +++ b/XDKSamples/System/FrontPanelText/FrontPanelText.vcxproj @@ -0,0 +1,386 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + FrontPanelText + {ba779f69-6a9a-4241-bcf9-f31773a00fd2} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + xboxfrontpanel.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelText/FrontPanelText.vcxproj.filters b/XDKSamples/System/FrontPanelText/FrontPanelText.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..944a62aefd26e12ef908e9709c9909761514993b --- /dev/null +++ b/XDKSamples/System/FrontPanelText/FrontPanelText.vcxproj.filters @@ -0,0 +1,203 @@ + + + + + 08894fad-0944-4509-ac54-76e4168a31ba + + + 475aafaf-0f93-4d52-b282-35d490d51f5d + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {60a91a7d-b3e9-431d-9922-8806484d55b8} + + + {cef3694d-314b-46ce-8c21-9239c8edbf3c} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + Assets\RasterFonts + + + \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelText/Main.cpp b/XDKSamples/System/FrontPanelText/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d108e6ea820d01b69e4d91a04a6364a40e759e6 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "FrontPanelText.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelText/Package.appxmanifest b/XDKSamples/System/FrontPanelText/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..4f6ad1eac134c77f186dec9166fba1a51067ecaf --- /dev/null +++ b/XDKSamples/System/FrontPanelText/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + FrontPanelText + Xbox Advanced Technology Group + Assets\StoreLogo.png + FrontPanelText + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/FrontPanelText/StepTimer.h b/XDKSamples/System/FrontPanelText/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/FrontPanelText/Telemetry.h b/XDKSamples/System/FrontPanelText/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/FrontPanelText/pch.cpp b/XDKSamples/System/FrontPanelText/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/FrontPanelText/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/FrontPanelText/pch.h b/XDKSamples/System/FrontPanelText/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..d8989911c651eba9457c37b583be5ccf5b201615 --- /dev/null +++ b/XDKSamples/System/FrontPanelText/pch.h @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This sample requires the March 2017 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "WICTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/FrontPanelText/readme.docx b/XDKSamples/System/FrontPanelText/readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..5bcd3455982a983c26eecfc2bafe3210045c24be Binary files /dev/null and b/XDKSamples/System/FrontPanelText/readme.docx differ diff --git a/XDKSamples/System/Gamepad/Assets/Logo.png b/XDKSamples/System/Gamepad/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/Gamepad/Assets/Logo.png differ diff --git a/XDKSamples/System/Gamepad/Assets/SmallLogo.png b/XDKSamples/System/Gamepad/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/Gamepad/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/Gamepad/Assets/SplashScreen.png b/XDKSamples/System/Gamepad/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/Gamepad/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/Gamepad/Assets/StoreLogo.png b/XDKSamples/System/Gamepad/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/Gamepad/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/Gamepad/Assets/WideLogo.png b/XDKSamples/System/Gamepad/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/Gamepad/Assets/WideLogo.png differ diff --git a/XDKSamples/System/Gamepad/DeviceResources.cpp b/XDKSamples/System/Gamepad/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/System/Gamepad/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/Gamepad/DeviceResources.h b/XDKSamples/System/Gamepad/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/System/Gamepad/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/Gamepad/Gamepad.cpp b/XDKSamples/System/Gamepad/Gamepad.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e730a48e4ec73511281cf07777a94e2dbc3aaa6 --- /dev/null +++ b/XDKSamples/System/Gamepad/Gamepad.cpp @@ -0,0 +1,309 @@ +//-------------------------------------------------------------------------------------- +// Gamepad.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Gamepad.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; +using namespace Windows::Foundation; +using namespace Windows::Xbox::Input; + +namespace GamepadManager +{ + IGamepad^ GetFirstGamepad() + { + IGamepad^ gamepad = nullptr; + + auto allGamepads = Gamepad::Gamepads; + if (allGamepads->Size > 0) + { + gamepad = allGamepads->GetAt(0); + } + + return gamepad; + } +}; + +Sample::Sample() +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_currentGamepad = GamepadManager::GetFirstGamepad(); + m_currentGamepadNeedsRefresh = false; + + Gamepad::GamepadAdded += ref new EventHandler([=](Platform::Object^, GamepadAddedEventArgs^ args) + { + m_currentGamepadNeedsRefresh = true; + }); + + Gamepad::GamepadRemoved += ref new EventHandler([=](Platform::Object^, GamepadRemovedEventArgs^ args) + { + m_currentGamepadNeedsRefresh = true; + }); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame"); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& ) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_currentGamepadNeedsRefresh) + { + auto mostRecentGamepad = GamepadManager::GetFirstGamepad(); + if (m_currentGamepad != mostRecentGamepad) + { + m_currentGamepad = mostRecentGamepad; + } + m_currentGamepadNeedsRefresh = false; + } + + if (m_currentGamepad == nullptr) + { + m_buttonString.clear(); + PIXEndEvent(); + return; + } + + m_reading = m_currentGamepad->GetCurrentReading(); + + m_buttonString = L"Buttons pressed: "; + + if (m_reading->IsDPadUpPressed) + { + m_buttonString += L"[DPad]Up "; + } + + if (m_reading->IsDPadDownPressed) + { + m_buttonString += L"[DPad]Down "; + } + + if (m_reading->IsDPadRightPressed) + { + m_buttonString += L"[DPad]Right "; + } + + if (m_reading->IsDPadLeftPressed) + { + m_buttonString += L"[DPad]Left "; + } + + if (m_reading->IsAPressed) + { + m_buttonString += L"[A] "; + } + + if (m_reading->IsBPressed) + { + m_buttonString += L"[B] "; + } + + if (m_reading->IsXPressed) + { + m_buttonString += L"[X] "; + } + + if (m_reading->IsYPressed) + { + m_buttonString += L"[Y] "; + } + + if (m_reading->IsLeftShoulderPressed) + { + m_buttonString += L"[LB] "; + } + + if (m_reading->IsRightShoulderPressed) + { + m_buttonString += L"[RB] "; + } + + if (m_reading->IsLeftThumbstickPressed) + { + m_buttonString += L"[LThumb] "; + } + + if (m_reading->IsRightThumbstickPressed) + { + m_buttonString += L"[RThumb] "; + } + + if (m_reading->IsMenuPressed) + { + m_buttonString += L"[Menu] "; + } + + if (m_reading->IsViewPressed) + { + m_buttonString += L"[View] "; + } + + m_leftTrigger = m_reading->LeftTrigger; + m_rightTrigger = m_reading->RightTrigger; + m_leftStickX = m_reading->LeftThumbstickX; + m_leftStickY = m_reading->LeftThumbstickY; + m_rightStickX = m_reading->RightThumbstickX; + m_rightStickY = m_reading->RightThumbstickY; + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto rect = m_deviceResources->GetOutputSize(); + auto safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + wchar_t tempString[256] = {}; + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + if (!m_buttonString.empty()) + { + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), m_buttonString.c_str(), pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[LT] %1.3f", m_leftTrigger); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[RT] %1.3f", m_rightTrigger); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[LThumb] X: %1.3f Y: %1.3f", m_leftStickX, m_leftStickY); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[RThumb] X: %1.3f Y: %1.3f", m_rightStickX, m_rightStickY); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + } + else + { + m_font->DrawString(m_spriteBatch.get(), L"No controller connected", pos, ATG::Colors::Orange); + } + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_24.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneController.spritefont"); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"gamepad.dds", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/Gamepad/Gamepad.h b/XDKSamples/System/Gamepad/Gamepad.h new file mode 100644 index 0000000000000000000000000000000000000000..eea3ba218e10514ffad2a634360fa48a34e91763 --- /dev/null +++ b/XDKSamples/System/Gamepad/Gamepad.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// Gamepad.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Render objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; + Microsoft::WRL::ComPtr m_background; + + //Gamepad states + Windows::Xbox::Input::IGamepadReading^ m_reading; + Windows::Xbox::Input::IGamepad^ m_currentGamepad; + + bool m_currentGamepadNeedsRefresh; + std::wstring m_buttonString; + double m_leftTrigger; + double m_rightTrigger; + double m_leftStickX; + double m_leftStickY; + double m_rightStickX; + double m_rightStickY; + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; +}; diff --git a/XDKSamples/System/Gamepad/Gamepad.sln b/XDKSamples/System/Gamepad/Gamepad.sln new file mode 100644 index 0000000000000000000000000000000000000000..2944284d2cb0a917eb564ac240d37f966145eb64 --- /dev/null +++ b/XDKSamples/System/Gamepad/Gamepad.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Gamepad", "Gamepad.vcxproj", "{E02A4300-4A99-4942-B968-FCF172750ED6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.ActiveCfg = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.Build.0 = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.Deploy.0 = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.ActiveCfg = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.Build.0 = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.Deploy.0 = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.ActiveCfg = Release|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.Build.0 = Release|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/Gamepad/Gamepad.vcxproj b/XDKSamples/System/Gamepad/Gamepad.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..5bb42a7b6dafc1218cdf918e276f83528dc3d9c9 --- /dev/null +++ b/XDKSamples/System/Gamepad/Gamepad.vcxproj @@ -0,0 +1,221 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + Gamepad + {e02a4300-4a99-4942-b968-fcf172750ed6} + en-US + Win32Proj + title + + v140 + 14.0 + Native + 8.1 + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/Gamepad/Gamepad.vcxproj.filters b/XDKSamples/System/Gamepad/Gamepad.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..64bab90a14fe81279520fd73a0eafa911253adb9 --- /dev/null +++ b/XDKSamples/System/Gamepad/Gamepad.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + a7240d26-11f1-47e9-b2d4-b13651be07aa + + + bf720e03-8486-4c01-982d-366c98ba03e9 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {8d6d0512-aede-4a5c-a1b8-fd2fdcf54365} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/Gamepad/Main.cpp b/XDKSamples/System/Gamepad/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4053ce5b8d1cc5b3bcc74e9d51cdc6241dc0b50b --- /dev/null +++ b/XDKSamples/System/Gamepad/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Gamepad.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/Gamepad/Package.appxmanifest b/XDKSamples/System/Gamepad/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..b514f3ac5304688a1dd2671d34a23e9e334b6076 --- /dev/null +++ b/XDKSamples/System/Gamepad/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + Gamepad + Xbox Advanced Technology Group + Assets\StoreLogo.png + Gamepad + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/Gamepad/Readme.docx b/XDKSamples/System/Gamepad/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..e7e2cd51cbd9cb4c5b1b3101545867c0b3e266d6 Binary files /dev/null and b/XDKSamples/System/Gamepad/Readme.docx differ diff --git a/XDKSamples/System/Gamepad/StepTimer.h b/XDKSamples/System/Gamepad/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/Gamepad/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/Gamepad/Telemetry.h b/XDKSamples/System/Gamepad/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/Gamepad/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/Gamepad/pch.cpp b/XDKSamples/System/Gamepad/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/Gamepad/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/Gamepad/pch.h b/XDKSamples/System/Gamepad/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..e783f2945cb13a2cd320cd4a56d94565a705419d --- /dev/null +++ b/XDKSamples/System/Gamepad/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GraphicsMemory.h" +#include "DDSTextureLoader.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/GamepadCppWinRT/Assets/Logo.png b/XDKSamples/System/GamepadCppWinRT/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/GamepadCppWinRT/Assets/Logo.png differ diff --git a/XDKSamples/System/GamepadCppWinRT/Assets/SmallLogo.png b/XDKSamples/System/GamepadCppWinRT/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/GamepadCppWinRT/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/GamepadCppWinRT/Assets/SplashScreen.png b/XDKSamples/System/GamepadCppWinRT/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/GamepadCppWinRT/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/GamepadCppWinRT/Assets/StoreLogo.png b/XDKSamples/System/GamepadCppWinRT/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/GamepadCppWinRT/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/GamepadCppWinRT/Assets/WideLogo.png b/XDKSamples/System/GamepadCppWinRT/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/GamepadCppWinRT/Assets/WideLogo.png differ diff --git a/XDKSamples/System/GamepadCppWinRT/DeviceResources.cpp b/XDKSamples/System/GamepadCppWinRT/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/GamepadCppWinRT/DeviceResources.h b/XDKSamples/System/GamepadCppWinRT/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.cpp b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95dc8963f018f2e8fe1f8749b2b102e612a43a64 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.cpp @@ -0,0 +1,324 @@ +//-------------------------------------------------------------------------------------- +// GamepadCppWinRT.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GamepadCppWinRT.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Xbox::Input; + +namespace GamepadManager +{ + IGamepad GetFirstGamepad() + { + IGamepad gamepad = nullptr; + + auto allGamepads = Gamepad::Gamepads(); + if (allGamepads.Size() > 0) + { + gamepad = allGamepads.GetAt(0); + } + + return gamepad; + } +}; + +Sample::Sample() : + m_reading(nullptr) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(::IUnknown* window) +{ + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_currentGamepad = GamepadManager::GetFirstGamepad(); + m_currentGamepadNeedsRefresh = false; + + Gamepad::GamepadAdded({ this, &Sample::OnGamepadAdded }); + Gamepad::GamepadRemoved({ this, &Sample::OnGamepadRemoved }); +} + +void Sample::OnGamepadAdded(winrt::Windows::Foundation::IInspectable const &, GamepadAddedEventArgs const &) +{ + m_currentGamepadNeedsRefresh = true; +} + +void Sample::OnGamepadRemoved(winrt::Windows::Foundation::IInspectable const &, GamepadRemovedEventArgs const &) +{ + m_currentGamepadNeedsRefresh = true; +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame"); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& ) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_currentGamepadNeedsRefresh) + { + auto mostRecentGamepad = GamepadManager::GetFirstGamepad(); + if (m_currentGamepad != mostRecentGamepad) + { + m_currentGamepad = mostRecentGamepad; + } + m_currentGamepadNeedsRefresh = false; + } + + if (m_currentGamepad == nullptr) + { + m_buttonString.clear(); + PIXEndEvent(); + return; + } + + m_reading = m_currentGamepad.GetCurrentReading(); + + m_buttonString = L"Buttons pressed: "; + + int exitComboPressed = 0; + + if (m_reading.IsDPadUpPressed()) + { + m_buttonString += L"[DPad]Up "; + } + + if (m_reading.IsDPadDownPressed()) + { + m_buttonString += L"[DPad]Down "; + } + + if (m_reading.IsDPadRightPressed()) + { + m_buttonString += L"[DPad]Right "; + } + + if (m_reading.IsDPadLeftPressed()) + { + m_buttonString += L"[DPad]Left "; + } + + if (m_reading.IsAPressed()) + { + m_buttonString += L"[A] "; + } + + if (m_reading.IsBPressed()) + { + m_buttonString += L"[B] "; + } + + if (m_reading.IsXPressed()) + { + m_buttonString += L"[X] "; + } + + if (m_reading.IsYPressed()) + { + m_buttonString += L"[Y] "; + } + + if (m_reading.IsLeftShoulderPressed()) + { + m_buttonString += L"[LB] "; + exitComboPressed += 1; + } + + if (m_reading.IsRightShoulderPressed()) + { + m_buttonString += L"[RB] "; + exitComboPressed += 1; + } + + if (m_reading.IsLeftThumbstickPressed()) + { + m_buttonString += L"[LThumb] "; + } + + if (m_reading.IsRightThumbstickPressed()) + { + m_buttonString += L"[RThumb] "; + } + + if (m_reading.IsMenuPressed()) + { + m_buttonString += L"[Menu] "; + exitComboPressed += 1; + } + + if (m_reading.IsViewPressed()) + { + m_buttonString += L"[View] "; + exitComboPressed += 1; + } + + m_leftTrigger = m_reading.LeftTrigger(); + m_rightTrigger = m_reading.RightTrigger(); + m_leftStickX = m_reading.LeftThumbstickX(); + m_leftStickY = m_reading.LeftThumbstickY(); + m_rightStickX = m_reading.RightThumbstickX(); + m_rightStickY = m_reading.RightThumbstickY(); + + if (exitComboPressed == 4) + ExitSample(); + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto rect = m_deviceResources->GetOutputSize(); + auto safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + wchar_t tempString[256] = {}; + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + if (!m_buttonString.empty()) + { + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), m_buttonString.c_str(), pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[LT] %1.3f", m_leftTrigger); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[RT] %1.3f", m_rightTrigger); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[LThumb] X: %1.3f Y: %1.3f", m_leftStickX, m_leftStickY); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + pos.y += m_font->GetLineSpacing() * 1.5f; + + swprintf(tempString, 255, L"[RThumb] X: %1.3f Y: %1.3f", m_rightStickX, m_rightStickY); + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), tempString, pos); + } + else + { + m_font->DrawString(m_spriteBatch.get(), L"No controller connected", pos, ATG::Colors::Orange); + } + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_24.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneController.spritefont"); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"gamepad.dds", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.h b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.h new file mode 100644 index 0000000000000000000000000000000000000000..d2212fd55700214b8ac33e09df1809d073c79cbb --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// GamepadCppWinRT.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "winrt\Windows.Xbox.Input.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(::IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Render objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; + Microsoft::WRL::ComPtr m_background; + + //Gamepad states + winrt::Windows::Xbox::Input::IGamepadReading m_reading; + winrt::Windows::Xbox::Input::IGamepad m_currentGamepad; + + void OnGamepadAdded(winrt::Windows::Foundation::IInspectable const & sender, winrt::Windows::Xbox::Input::GamepadAddedEventArgs const & args); + void OnGamepadRemoved(winrt::Windows::Foundation::IInspectable const & sender, winrt::Windows::Xbox::Input::GamepadRemovedEventArgs const & args); + + bool m_currentGamepadNeedsRefresh; + std::wstring m_buttonString; + double m_leftTrigger; + double m_rightTrigger; + double m_leftStickX; + double m_leftStickY; + double m_rightStickX; + double m_rightStickY; + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; +}; diff --git a/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.sln b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.sln new file mode 100644 index 0000000000000000000000000000000000000000..ff21658f867e420032aa95ecd565ebf4d7c5b1a2 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamepadCppWinRT", "GamepadCppWinRT.vcxproj", "{E02A4300-4A99-4942-B968-FCF172750ED6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.ActiveCfg = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.Build.0 = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Debug|Durango.Deploy.0 = Debug|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.ActiveCfg = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.Build.0 = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Profile|Durango.Deploy.0 = Profile|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.ActiveCfg = Release|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.Build.0 = Release|Durango + {E02A4300-4A99-4942-B968-FCF172750ED6}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.vcxproj b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..c0e61bdd232bd2d27b0a6bbb0423c08acb97f5e9 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.vcxproj @@ -0,0 +1,227 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + Gamepad + {e02a4300-4a99-4942-b968-fcf172750ed6} + en-US + Win32Proj + title + + v140 + 14.0 + Native + 8.1 + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + false + /std:c++latest %(AdditionalOptions) + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + /std:c++latest %(AdditionalOptions) + false + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + /std:c++latest %(AdditionalOptions) + false + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.vcxproj.filters b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..9eb13f27e319372bbfd6d7f64fb31f2203eaa0e6 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/GamepadCppWinRT.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + a7240d26-11f1-47e9-b2d4-b13651be07aa + + + bf720e03-8486-4c01-982d-366c98ba03e9 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {8d6d0512-aede-4a5c-a1b8-fd2fdcf54365} + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/GamepadCppWinRT/Main.cpp b/XDKSamples/System/GamepadCppWinRT/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff711dc2f9fd86410116777aae1e94e5bbdfa0e7 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/Main.cpp @@ -0,0 +1,142 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GamepadCppWinRT.h" + +#include "Telemetry.h" + +using namespace winrt::Windows::ApplicationModel; +using namespace winrt::Windows::ApplicationModel::Core; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::Foundation; +using namespace DirectX; + +class ViewProvider final : public winrt::implements +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + void Initialize(CoreApplicationView const & applicationView) + { + applicationView.Activated({ this, &ViewProvider::OnActivated }); + + CoreApplication::Suspending({ this, &ViewProvider::OnSuspending }); + + CoreApplication::Resuming({ this, &ViewProvider::OnResuming }); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + void Uninitialize() + { + m_sample.reset(); + } + + void SetWindow(CoreWindow const & window) + { + window.Closed({ this, &ViewProvider::OnWindowClosed }); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(winrt::get_abi(window)); + } + + void Load(winrt::hstring const &) + { + } + + void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView const & /*applicationView*/, IActivatedEventArgs const & /*args*/) + { + CoreWindow::GetForCurrentThread().Activate(); + } + + void OnSuspending(IInspectable const & /*sender*/, SuspendingEventArgs const & args) + { + auto deferral = args.SuspendingOperation().GetDeferral(); + + std::async(std::launch::async, [this, deferral]() + { + m_sample->OnSuspending(); + + deferral.Complete(); + }); + } + + void OnResuming(IInspectable const & /*sender*/, IInspectable const & /*args*/) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow const & /*sender*/, CoreWindowEventArgs const & /*args*/) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +class ViewProviderFactory final : public winrt::implements +{ +public: + IFrameworkView CreateView() + { + return winrt::make(); + } +}; + +// Entry point +int WINAPIV WinMain() +{ + winrt::init_apartment(); + + SetThreadAffinityMask(GetCurrentThread(), 0x1); + ViewProviderFactory viewProviderFactory; + CoreApplication::Run(viewProviderFactory); + + winrt::uninit_apartment(); + return 0; +} + +// Exit helper +void ExitSample() +{ + winrt::Windows::ApplicationModel::Core::CoreApplication::Exit(); +} diff --git a/XDKSamples/System/GamepadCppWinRT/Package.appxmanifest b/XDKSamples/System/GamepadCppWinRT/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..b514f3ac5304688a1dd2671d34a23e9e334b6076 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + Gamepad + Xbox Advanced Technology Group + Assets\StoreLogo.png + Gamepad + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/GamepadCppWinRT/Readme.docx b/XDKSamples/System/GamepadCppWinRT/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..eeb6bcbeec7a479feeb54e9404bf07a4be5ac586 Binary files /dev/null and b/XDKSamples/System/GamepadCppWinRT/Readme.docx differ diff --git a/XDKSamples/System/GamepadCppWinRT/StepTimer.h b/XDKSamples/System/GamepadCppWinRT/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/GamepadCppWinRT/Telemetry.h b/XDKSamples/System/GamepadCppWinRT/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/GamepadCppWinRT/pch.cpp b/XDKSamples/System/GamepadCppWinRT/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/GamepadCppWinRT/pch.h b/XDKSamples/System/GamepadCppWinRT/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..4487e24b92a8cf8684d287022aa08511d601a651 --- /dev/null +++ b/XDKSamples/System/GamepadCppWinRT/pch.h @@ -0,0 +1,74 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This sample requires the March 2017 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "winrt/Windows.ApplicationModel.h" +#include "winrt/Windows.ApplicationModel.Core.h" +#include "winrt/Windows.ApplicationModel.Activation.h" +#include "winrt/Windows.UI.Core.h" +#include "winrt/Windows.Foundation.h" + +#include "GraphicsMemory.h" +#include "DDSTextureLoader.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/GamepadVibration/Assets/Logo.png b/XDKSamples/System/GamepadVibration/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/GamepadVibration/Assets/Logo.png differ diff --git a/XDKSamples/System/GamepadVibration/Assets/SmallLogo.png b/XDKSamples/System/GamepadVibration/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/GamepadVibration/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/GamepadVibration/Assets/SplashScreen.png b/XDKSamples/System/GamepadVibration/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/GamepadVibration/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/GamepadVibration/Assets/StoreLogo.png b/XDKSamples/System/GamepadVibration/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/GamepadVibration/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/GamepadVibration/Assets/WideLogo.png b/XDKSamples/System/GamepadVibration/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/GamepadVibration/Assets/WideLogo.png differ diff --git a/XDKSamples/System/GamepadVibration/DeviceResources.cpp b/XDKSamples/System/GamepadVibration/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/GamepadVibration/DeviceResources.h b/XDKSamples/System/GamepadVibration/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/System/GamepadVibration/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/GamepadVibration/GamepadVibration.cpp b/XDKSamples/System/GamepadVibration/GamepadVibration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96d00075ee5c4df7ad726ab8ec4f0a03a0b5f9a3 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/GamepadVibration.cpp @@ -0,0 +1,551 @@ +//-------------------------------------------------------------------------------------- +// GamepadVibration.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GamepadVibration.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; +using namespace Windows::Xbox::Input; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; + +namespace +{ + static const wchar_t* c_TRIGGER_EFFECT_NAME_TEXT[Sample::TRIGGEREFFECTS_MAX] = + { + L"\n", + L"\n", + L"\n", + L"\n", + L"\n" + }; + + static const wchar_t* c_TRIGGER_EFFECT_DESC_TEXT[Sample::TRIGGEREFFECTS_MAX] = + { + L"Use the [LT] and [RT] to test the feedback\n" + L"function of the gamepad. The envelope is set based on\n" + L"the trigger position. The more you pull the triggers,\n" + L"the more feedback you will feel.", + + L"Impulse triggers can provide feedback about the environment.\n" + L"Assuming the player is driving a car, this example uses\n" + L"the impulse triggers to inform a flat tire on the left side.", + + L"Demonstrates how impulse triggers can be combined with the\n" + L"vibration motors to simulate weapon firing and recoil.\n" + L"Press the [LT] to activate the effect.", + + L"Impulse triggers can relay information about the player\'s\n" + L"in-game representation. Here we relay the character\'s\n" + L"heartbeat, which can be used to let the player know that\n" + L"their character is exhausted.", + + L"Impulse triggers can relay information external to the\n" + L"player. This example use the impulse triggers to simulate\n" + L"footsteps which could indicate the presence of a nearby\n" + L"character." + }; + + uint32_t flatTireLeftTriggerDurations[] = { 33, 80, 16 }; + float flatTireLeftTriggerLevels[] = { 0.8f, 0.0f, 0.0f }; + + uint32_t gunWithRecoilLeftTriggerDurations[] = { 20, 10, 90, 10000 }; + float gunWithRecoilLeftTriggerLevels[] = { 1.0f, 0.0f, 0.0f, 0.0f }; + + uint32_t heartbeatLeftTriggerDurations[] = { 25, 200, 25, 10, 745 }; + float heartbeatLeftTriggerLevels[] = { 0.2f, 0.0f, 0.0f, 0.0f, 0.0f }; + uint32_t heartbeatRightTriggerDurations[] = { 25, 200, 25, 10, 745 }; + float heartbeatRightTriggerLevels[] = { 0.0f, 0.0f, 0.2f, 0.02f, 0.0f }; + + uint32_t footstepsLeftTriggerDurations[] = { 25, 600, 25, 600 }; + float footstepsLeftTriggerLevels[] = { 0.3f, 0.0f, 0.0f, 0.0f }; + uint32_t footstepsRightTriggerDurations[] = { 25, 600, 25, 600 }; + float footstepsRightTriggerLevels[] = { 0.0f, 0.0f, 0.3f, 0.0f }; +} + +//-------------------------------------------------------------------------------------- +// Helper class for managing the gamepads +//-------------------------------------------------------------------------------------- +namespace GamepadManager +{ + IGamepad^ GetMostRecentGamepad() + { + IGamepad^ gamepad = nullptr; + + auto allGamepads = Gamepad::Gamepads; + if (allGamepads->Size > 0) + { + gamepad = allGamepads->GetAt(0); + } + + return gamepad; + } + + bool IsGamepadValid(IGamepad^ gamepad) + { + IIterator^ it = Gamepad::Gamepads->First(); + + while (it->HasCurrent) + { + if (gamepad == it->Current) + { + return true; + } + + it->MoveNext(); + } + + return false; + } +}; + +Sample::Sample() +{ + m_deviceResources = std::make_unique(); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_selectedTriggerEffect = TRIGGEREFFECTS::TRIGGEREFFECTS_IMPULSETEST; + + m_currentGamepad = GamepadManager::GetMostRecentGamepad(); + m_currentGamepadNeedsRefresh = false; + m_connected = false; + + Gamepad::GamepadAdded += ref new EventHandler([=](Platform::Object^, GamepadAddedEventArgs^ args) + { + m_currentGamepadNeedsRefresh = true; + }); + + Gamepad::GamepadRemoved += ref new EventHandler([=](Platform::Object^, GamepadRemovedEventArgs^ args) + { + m_currentGamepadNeedsRefresh = true; + }); + + QueryPerformanceFrequency(reinterpret_cast(&m_frequency)); +} + +void Sample::InitializeCurrentGamepad() +{ + if (m_currentGamepad) + { + m_reading = m_currentGamepad->GetCurrentReading(); + + ZeroMemory(&m_vibration, sizeof(GamepadVibration)); + + m_dPadPressed = false; + + m_selectedTriggerEffect = TRIGGEREFFECTS::TRIGGEREFFECTS_IMPULSETEST; + InitializeImpulseTriggerEffects(); + } +} + +void Sample::ShutdownCurrentGamepad() +{ + if (m_currentGamepad && GamepadManager::IsGamepadValid(m_currentGamepad)) + { + GamepadVibration vibration = { 0 }; + m_currentGamepad->SetVibration(vibration); + } +} + +//-------------------------------------------------------------------------------------- +// Name: InitializeImpulseTriggerEffects() +// Desc: Clear variables used by the tigger effects and initialize them as needed for +// the currently selected effect. +//-------------------------------------------------------------------------------------- +void Sample::InitializeImpulseTriggerEffects() +{ + m_leftTriggerIndex = 0; + m_rightTriggerIndex = 0; + + m_leftMotorSpeed = 0; + m_leftTriggerLevel = 0; + m_rightMotorSpeed = 0; + m_rightTriggerLevel = 0; + + m_triggerEffectCounter = 0; + switch (m_selectedTriggerEffect) + { + case TRIGGEREFFECTS::TRIGGEREFFECTS_IMPULSETEST: + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_FLATTIRE: + m_leftTriggerArraySize = 3; + + m_pLeftTriggerDurations = flatTireLeftTriggerDurations; + m_pLeftTriggerLevels = flatTireLeftTriggerLevels; + + // Set the timing for the transition to the second vibration level + // Further transition timings will be handled by the transition code. + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_GUNWITHRECOIL: + m_leftTriggerArraySize = 4; + + m_pLeftTriggerDurations = gunWithRecoilLeftTriggerDurations; + m_pLeftTriggerLevels = gunWithRecoilLeftTriggerLevels; + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_HEARTBEAT: + m_leftTriggerArraySize = 5; + m_rightTriggerArraySize = 5; + + m_pLeftTriggerDurations = heartbeatLeftTriggerDurations; + m_pLeftTriggerLevels = heartbeatLeftTriggerLevels; + m_pRightTriggerDurations = heartbeatRightTriggerDurations; + m_pRightTriggerLevels = heartbeatRightTriggerLevels; + + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + m_rightTriggerIndexUpdateTime = m_counter + (m_frequency * m_pRightTriggerDurations[m_rightTriggerIndex]) / 1000; + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_FOOTSTEPS: + m_leftTriggerArraySize = 4; + m_rightTriggerArraySize = 4; + + m_pLeftTriggerDurations = footstepsLeftTriggerDurations; + m_pLeftTriggerLevels = footstepsLeftTriggerLevels; + m_pRightTriggerDurations = footstepsRightTriggerDurations; + m_pRightTriggerLevels = footstepsRightTriggerLevels; + + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + m_rightTriggerIndexUpdateTime = m_counter + (m_frequency * m_pRightTriggerDurations[m_rightTriggerIndex]) / 1000; + break; + + default: + assert(false); + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame"); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& ) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_currentGamepadNeedsRefresh) + { + auto mostRecentGamepad = GamepadManager::GetMostRecentGamepad(); + if (m_currentGamepad != mostRecentGamepad) + { + ShutdownCurrentGamepad(); + m_currentGamepad = mostRecentGamepad; + InitializeCurrentGamepad(); + } + m_currentGamepadNeedsRefresh = false; + } + + if (m_currentGamepad == nullptr) + { + m_connected = false; + PIXEndEvent(); + return; + } + + m_connected = true; + + m_reading = m_currentGamepad->GetCurrentReading(); + + if (m_reading->IsViewPressed) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (!m_dPadPressed) + { + if (m_reading->IsDPadRightPressed) + { + m_dPadPressed = true; + m_selectedTriggerEffect = static_cast((static_cast(m_selectedTriggerEffect) + 1) % TRIGGEREFFECTS_MAX); + InitializeImpulseTriggerEffects(); + } + else if (m_reading->IsDPadLeftPressed) + { + m_dPadPressed = true; + m_selectedTriggerEffect = static_cast((static_cast(m_selectedTriggerEffect) + TRIGGEREFFECTS_MAX - 1) % TRIGGEREFFECTS_MAX); + InitializeImpulseTriggerEffects(); + } + } + else + { + if (static_cast(m_reading->Buttons & (GamepadButtons::DPadRight | GamepadButtons::DPadLeft)) == 0) + { + m_dPadPressed = false; + } + } + + switch (m_selectedTriggerEffect) + { + case TRIGGEREFFECTS::TRIGGEREFFECTS_IMPULSETEST: + // This example uses a very simple vibration envelope waveform by setting the vibration + // levels to the current trigger values. This means the more you pull the triggers, the more + // vibration you will feel. + m_leftTriggerLevel = m_reading->LeftTrigger; + m_rightTriggerLevel = m_reading->RightTrigger; + m_leftMotorSpeed = m_reading->LeftTrigger; + m_rightMotorSpeed = m_reading->RightTrigger; + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_FLATTIRE: + m_leftTriggerLevel = m_pLeftTriggerLevels[m_leftTriggerIndex]; + + // If we've reached or passed the transition time, update m_leftTriggerIndexUpdateTime + // with the next transition time and update the effect index. + // This will cause the effect to change in the next loop iteration. + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + if (m_counter > m_leftTriggerIndexUpdateTime) + { + m_leftTriggerIndex = (m_leftTriggerIndex + 1) % m_leftTriggerArraySize; + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + } + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_GUNWITHRECOIL: + switch (m_triggerEffectCounter) + { + case 0: // Wait for the trigger to be fully released before + // the effect can begin + if (m_reading->LeftTrigger <= 1.0f / 255.0f) + { + m_triggerEffectCounter = 1; + } + break; + + case 1: // Wait for the trigger to be depressed enough to cause the gun to fire + if (m_reading->LeftTrigger >= 32.0f / 255.0f) + { + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + m_triggerEffectCounter = 2; + } + break; + + case 2: // Delay recoil a little after the bullet has left the gun + m_leftTriggerLevel = m_pLeftTriggerLevels[m_leftTriggerIndex]; + + if (m_leftTriggerIndex == 2) + { + m_leftMotorSpeed = 1.0f; + m_rightMotorSpeed = 1.0f; + } + else + { + m_leftMotorSpeed = 0.0f; + m_rightMotorSpeed = 0.0f; + } + + if (m_leftTriggerIndex == 3) + { + m_leftTriggerIndex = 0; + m_triggerEffectCounter = 0; + break; + } + + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + if (m_counter > m_leftTriggerIndexUpdateTime) + { + m_leftTriggerIndex = (m_leftTriggerIndex + 1) % m_leftTriggerArraySize; + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + } + break; + } + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_HEARTBEAT: + // use the left level/duration for both triggers + m_leftTriggerLevel = m_pLeftTriggerLevels[m_leftTriggerIndex]; + m_rightTriggerLevel = m_pRightTriggerLevels[m_rightTriggerIndex]; + + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + if (m_counter > m_leftTriggerIndexUpdateTime) + { + m_leftTriggerIndex = (m_leftTriggerIndex + 1) % m_leftTriggerArraySize; + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + } + if (m_counter > m_rightTriggerIndexUpdateTime) + { + m_rightTriggerIndex = (m_rightTriggerIndex + 1) % m_rightTriggerArraySize; + m_rightTriggerIndexUpdateTime = m_counter + (m_frequency * m_pRightTriggerDurations[m_rightTriggerIndex]) / 1000; + } + break; + + case TRIGGEREFFECTS::TRIGGEREFFECTS_FOOTSTEPS: + m_leftTriggerLevel = m_pLeftTriggerLevels[m_leftTriggerIndex]; + m_rightTriggerLevel = m_pRightTriggerLevels[m_rightTriggerIndex]; + + QueryPerformanceCounter(reinterpret_cast(&m_counter)); + if (m_counter > m_leftTriggerIndexUpdateTime) + { + m_leftTriggerIndex = (m_leftTriggerIndex + 1) % m_leftTriggerArraySize; + m_leftTriggerIndexUpdateTime = m_counter + (m_frequency * m_pLeftTriggerDurations[m_leftTriggerIndex]) / 1000; + } + if (m_counter > m_rightTriggerIndexUpdateTime) + { + m_rightTriggerIndex = (m_rightTriggerIndex + 1) % m_rightTriggerArraySize; + m_rightTriggerIndexUpdateTime = m_counter + (m_frequency * m_pRightTriggerDurations[m_rightTriggerIndex]) / 1000; + } + break; + + default: + assert(false); + } + + m_vibration.LeftMotorLevel = m_leftMotorSpeed; + m_vibration.RightMotorLevel = m_rightMotorSpeed; + m_vibration.LeftTriggerLevel = m_leftTriggerLevel; + m_vibration.RightTriggerLevel = m_rightTriggerLevel; + m_currentGamepad->SetVibration(m_vibration); + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto rect = m_deviceResources->GetOutputSize(); + auto safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(rect.right, rect.bottom); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + if (m_connected) + { + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), + L"Use the [DPad] Left and Right to select a vibration effect.", pos, ATG::Colors::OffWhite); + pos.y += m_font->GetLineSpacing() * 2.f; + + // Draw description + m_font->DrawString(m_spriteBatch.get(), c_TRIGGER_EFFECT_NAME_TEXT[static_cast(m_selectedTriggerEffect)], pos, ATG::Colors::Green); + pos.y += m_font->GetLineSpacing() * 1.5f; + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), c_TRIGGER_EFFECT_DESC_TEXT[static_cast(m_selectedTriggerEffect)], pos); + } + else + { + m_font->DrawString(m_spriteBatch.get(), L"No controller connected", pos, ATG::Colors::Orange); + } + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneControllerLegendSmall.spritefont"); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"gamepad.dds", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/GamepadVibration/GamepadVibration.h b/XDKSamples/System/GamepadVibration/GamepadVibration.h new file mode 100644 index 0000000000000000000000000000000000000000..f282f8c6e4ff1b1ea6e4b71917c00134b7630515 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/GamepadVibration.h @@ -0,0 +1,101 @@ +//-------------------------------------------------------------------------------------- +// GamepadVibration.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + static const int TRIGGEREFFECTS_MAX = 5; + + enum class TRIGGEREFFECTS + { + TRIGGEREFFECTS_IMPULSETEST = 0, + TRIGGEREFFECTS_FLATTIRE, + TRIGGEREFFECTS_GUNWITHRECOIL, + TRIGGEREFFECTS_HEARTBEAT, + TRIGGEREFFECTS_FOOTSTEPS + }; + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + + void InitializeCurrentGamepad(); + void ShutdownCurrentGamepad(); + void InitializeImpulseTriggerEffects(); +private: + + static const int MAX_PLAYER_COUNT = 8; + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Render objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; + Microsoft::WRL::ComPtr m_background; + + //Gamepad states + Windows::Xbox::Input::IGamepadReading^ m_reading; + Windows::Xbox::Input::IGamepad^ m_currentGamepad; + Windows::Xbox::Input::GamepadVibration m_vibration; + + bool m_currentGamepadNeedsRefresh; + bool m_connected; + float m_leftMotorSpeed; + float m_rightMotorSpeed; + float m_leftTriggerLevel; + float m_rightTriggerLevel; + bool m_dPadPressed; + + // Variables used to control the Impulse Trigger Effects + TRIGGEREFFECTS m_selectedTriggerEffect; // Effect currently selected + DWORD m_triggerEffectCounter; // General purpose counter for use by trigger effects + + size_t m_leftTriggerArraySize; + uint32_t* m_pLeftTriggerDurations; + float* m_pLeftTriggerLevels; + size_t m_rightTriggerArraySize; + uint32_t* m_pRightTriggerDurations; + float* m_pRightTriggerLevels; + uint32_t m_leftTriggerIndex; + uint32_t m_rightTriggerIndex; + + uint64_t m_frequency; + uint64_t m_counter; + uint64_t m_leftTriggerIndexUpdateTime; + uint64_t m_rightTriggerIndexUpdateTime; + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; + +}; diff --git a/XDKSamples/System/GamepadVibration/GamepadVibration.sln b/XDKSamples/System/GamepadVibration/GamepadVibration.sln new file mode 100644 index 0000000000000000000000000000000000000000..a3afd90d5b0a32ceb103ff5173f901e50fe39cde --- /dev/null +++ b/XDKSamples/System/GamepadVibration/GamepadVibration.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamepadVibration", "GamepadVibration.vcxproj", "{184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Debug|Durango.ActiveCfg = Debug|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Debug|Durango.Build.0 = Debug|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Debug|Durango.Deploy.0 = Debug|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Profile|Durango.ActiveCfg = Profile|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Profile|Durango.Build.0 = Profile|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Profile|Durango.Deploy.0 = Profile|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Release|Durango.ActiveCfg = Release|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Release|Durango.Build.0 = Release|Durango + {184DA3B7-D563-42A9-85DE-BD0D5D8D8F7C}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/GamepadVibration/GamepadVibration.vcxproj b/XDKSamples/System/GamepadVibration/GamepadVibration.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..efce0f9e58d182de1116c2a0fda4ca118eeac90a --- /dev/null +++ b/XDKSamples/System/GamepadVibration/GamepadVibration.vcxproj @@ -0,0 +1,220 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + GamepadVibration + {184da3b7-d563-42a9-85de-bd0d5d8d8f7c} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/GamepadVibration/GamepadVibration.vcxproj.filters b/XDKSamples/System/GamepadVibration/GamepadVibration.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..b7ac6f4d1a992c9736e7927d08c9823a5cf12a96 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/GamepadVibration.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + 56263d3f-e0b4-4202-b82a-03ce94ad4372 + + + 9874d534-3fc0-40f2-8b50-73c26a83334e + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {b508b5b7-3f33-4d53-b141-7a6a91c4af4c} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/GamepadVibration/Main.cpp b/XDKSamples/System/GamepadVibration/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5dfa1c51246788292e72ad8cfcc552c7b4158776 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GamepadVibration.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/GamepadVibration/Package.appxmanifest b/XDKSamples/System/GamepadVibration/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..ef20a4c5fbde10c1c8223d86e56e8f407cd7aeab --- /dev/null +++ b/XDKSamples/System/GamepadVibration/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + GamepadVibration + Xbox Advanced Technology Group + Assets\StoreLogo.png + GamepadVibration + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/GamepadVibration/Readme.docx b/XDKSamples/System/GamepadVibration/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..64e45844ff838053f222f9205bc54fe50bc3ea3c Binary files /dev/null and b/XDKSamples/System/GamepadVibration/Readme.docx differ diff --git a/XDKSamples/System/GamepadVibration/StepTimer.h b/XDKSamples/System/GamepadVibration/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/GamepadVibration/Telemetry.h b/XDKSamples/System/GamepadVibration/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/GamepadVibration/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/GamepadVibration/pch.cpp b/XDKSamples/System/GamepadVibration/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/GamepadVibration/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/GamepadVibration/pch.h b/XDKSamples/System/GamepadVibration/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..e783f2945cb13a2cd320cd4a56d94565a705419d --- /dev/null +++ b/XDKSamples/System/GamepadVibration/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GraphicsMemory.h" +#include "DDSTextureLoader.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/Assets/Logo.png b/XDKSamples/System/MemoryBanks/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/MemoryBanks/Assets/Logo.png differ diff --git a/XDKSamples/System/MemoryBanks/Assets/SmallLogo.png b/XDKSamples/System/MemoryBanks/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/MemoryBanks/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/MemoryBanks/Assets/SplashScreen.png b/XDKSamples/System/MemoryBanks/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/MemoryBanks/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/MemoryBanks/Assets/StoreLogo.png b/XDKSamples/System/MemoryBanks/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/MemoryBanks/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/MemoryBanks/Assets/WideLogo.png b/XDKSamples/System/MemoryBanks/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/MemoryBanks/Assets/WideLogo.png differ diff --git a/XDKSamples/System/MemoryBanks/BankSwitchingMemory.cpp b/XDKSamples/System/MemoryBanks/BankSwitchingMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb89271c6daeaa313fd0697405e0a8a050b712a9 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/BankSwitchingMemory.cpp @@ -0,0 +1,47 @@ +//-------------------------------------------------------------------------------------- +// BankSwitchingMemory.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryDemo.h" + +namespace ATG +{ + bool MemoryDemo::TestBankSwitching() + { + try + { + m_memoryBank.ReleaseBank(); + if (!m_memoryBank.CommitRotateBanks(c_memoryBankSize * sizeof(uint32_t), 2)) + throw std::logic_error("Unable to commit rotated banks"); + uint32_t *bank0 = reinterpret_cast (m_memoryBank.get(0)); + uint32_t *bank1 = reinterpret_cast (m_memoryBank.get(1)); + for (uint32_t i = 0; i < c_memoryBankSize; i++) + { + bank0[i] = i; + bank1[i] = (1 << 24) + i; + } + + m_memoryBank.SwapBanks(0, 1); + + for (uint32_t i = 0; i < c_memoryBankSize; i++) + { + if (bank1[i] != i) + throw std::logic_error("Bank switching failed with incorrect data in the original first bank"); + if (bank0[i] != ((1 << 24) + i)) + throw std::logic_error("Bank switching failed with incorrect data in the original second bank"); + } + } + catch (const std::logic_error& what) + { + OutputDebugStringA(what.what()); + m_memoryBank.ReleaseBank(); + return false; + } + m_memoryBank.ReleaseBank(); + return true; + } +} diff --git a/XDKSamples/System/MemoryBanks/DeviceResources.cpp b/XDKSamples/System/MemoryBanks/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..051840a6dab4898c0c5aed915a810f0ac27ad297 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/DeviceResources.cpp @@ -0,0 +1,237 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, bool fastSemantics) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_fastSemantics(fastSemantics) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_fastSemantics) + { + creationFlags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_fastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if (m_fastSemantics && decompressFlags) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/MemoryBanks/DeviceResources.h b/XDKSamples/System/MemoryBanks/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..a74ce25c71af7f6b9a766ec071b419b131d991e9 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/DeviceResources.h @@ -0,0 +1,66 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + bool fastSemantics = false); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + bool m_fastSemantics; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/FixedMemory.cpp b/XDKSamples/System/MemoryBanks/FixedMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14e7d417eecf80023e6c0f7d10bd2f658247d5b8 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/FixedMemory.cpp @@ -0,0 +1,112 @@ +//-------------------------------------------------------------------------------------- +// FixedMemory.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryDemo.h" + +namespace ATG +{ + char *MemoryDemo::c_fixedTestDataFilename = "t:\\staticMemoryFixedTestData.dat"; + + // Load the binary tree data from disk and then validate the data + // The binary tree is allocated from the single bank allocated at a fixed address + bool MemoryDemo::TestFixedAddress() + { + try + { + m_memoryBank.ReleaseBank(); + if (!LoadFixedAddress()) + throw std::logic_error("Unable to load fixed address data"); + if (!ValidateData(m_rootNode, false, 0)) + throw std::logic_error("Failed to validate fixed address data"); + } + catch (const std::logic_error what) + { + OutputDebugStringA(what.what()); + m_memoryBank.ReleaseBank(); + return false; + } + return true; + } + // load the binary tree from disk, since the tree is allocated from one memory bank a single read from disk is enough + // Since the memory bank is allocated at the same address as the data was saved there is no need to fixup the internal addresses + // They are already correct since data was loaded back into the same base address as it was saved + bool MemoryDemo::LoadFixedAddress() + { + FILE *file = nullptr; + try + { + fopen_s(&file, c_fixedTestDataFilename, "rb"); + if (!file) + throw std::logic_error("unable to open data file\n"); + uintptr_t savedAddress; + if (fread(&savedAddress, sizeof(savedAddress), 1, file) != 1) + throw std::logic_error("unable to read fixed data file\n"); + + if (!m_memoryBank.CommitBank(c_testDataAllocatorSize * sizeof(TestData), savedAddress)) + throw std::logic_error("unable to commit memory at fixed memory address\n"); + if (m_memoryBank.get() != reinterpret_cast (savedAddress)) + throw std::logic_error("committed memory at the wrong address in Loading fixed data\n"); + + if (fread(m_memoryBank, sizeof(TestData), c_testDataAllocatorSize, file) != c_testDataAllocatorSize) + throw std::logic_error("unable to read fixed data file\n"); + fclose(file); + m_rootNode = reinterpret_cast (m_memoryBank.get()); + } + catch (const std::exception& what) + { + OutputDebugStringA(what.what()); + if (file) + fclose(file); + m_memoryBank.ReleaseBank(); + m_rootNode = nullptr; + return false; + } + return true; + } + + bool MemoryDemo::CreateFixedTestDataFile() + { + FILE *file = nullptr; + TestData *stackAllocator = nullptr; + try + { + // Allocate a block of memory and let the OS pick it's location + stackAllocator = reinterpret_cast (VirtualAlloc(nullptr, sizeof(TestData) * c_testDataAllocatorSize, MEM_RESERVE, PAGE_READWRITE)); + if (!stackAllocator) + return false; + stackAllocator = reinterpret_cast (VirtualAlloc(stackAllocator, sizeof(TestData) * c_testDataAllocatorSize, MEM_COMMIT, PAGE_READWRITE)); + // Save off the address for later loading of the data + + size_t stackAllocatorIndex = 0; + TestData *rootNode = &(stackAllocator[stackAllocatorIndex++]); + if (!InternalCreateTestData(rootNode, 1, stackAllocator, stackAllocatorIndex)) + throw std::logic_error("unable to create test tree\n"); + + fopen_s(&file, c_fixedTestDataFilename, "wb"); + if (!file) + throw std::logic_error("unable to create data file\n"); + if (fwrite(&stackAllocator, sizeof(stackAllocator), 1, file) != 1) + throw std::logic_error("unable to save fixed data file\n"); + if (fwrite(stackAllocator, sizeof(TestData), c_testDataAllocatorSize, file) != c_testDataAllocatorSize) + throw std::logic_error("unable to save fixed data file\n"); + fclose(file); + VirtualFree(stackAllocator, 0, MEM_RELEASE); + } + catch (const std::exception& what) + { + OutputDebugStringA(what.what()); + if (file) + fclose(file); + if (stackAllocator) + VirtualFree(stackAllocator, 0, MEM_RELEASE); + return false; + } + + return true; + } +} diff --git a/XDKSamples/System/MemoryBanks/Main.cpp b/XDKSamples/System/MemoryBanks/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65f8a675e9e33233c35ed1302d945c226b669821 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/Main.cpp @@ -0,0 +1,144 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryBanks.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH + 1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/MemoryBank.h b/XDKSamples/System/MemoryBanks/MemoryBank.h new file mode 100644 index 0000000000000000000000000000000000000000..db5667c8c190c18e2139140aca9547302fcb1f87 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryBank.h @@ -0,0 +1,296 @@ +//-------------------------------------------------------------------------------------- +// MemoryBank.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Creates and manages a memory bank. +// Can either support a basic single memory bank +// A shared memory bank where multiple virtual pages are mapped to the same physical page +// A bank that supports page swapping or rotating. Where virtual addresses are moved between multiple physical addresses +class MemoryBank +{ +private: + enum class BankType + { + UNDEFINED, + BASIC_BANK, + SHARED_BANK, + ROTATE_BANK, + }; + + // mapping physical pages to virtual pages requires either 64k or 4MB pages for both + static const size_t c_SIZE_PER_LARGE_PHYSICAL_PAGE = (64 * 1024); + static const size_t c_SIZE_PER_4MB_PHYSICAL_PAGE = (4 * 1024 * 1024); + + BankType m_bankType; + void **m_banks; // virtual address of each bank in this group + size_t m_numberOfBanks; + size_t m_bankSize; + + // used for mapping physical pages + size_t m_numberOfPhysicalBanks; + size_t **m_physicalPageArray; // list of 64k pages for each bank + size_t m_numberOfPhysicalPagesPerBank; // physical pages are maintained as 64k pages + +public: + MemoryBank(const MemoryBank&) = delete; + MemoryBank& operator=(const MemoryBank&) = delete; + MemoryBank(MemoryBank&& rhs) = default; + + MemoryBank() :m_banks(nullptr), m_physicalPageArray(nullptr), m_numberOfPhysicalBanks(0), m_numberOfPhysicalPagesPerBank(0), m_numberOfBanks(0), m_bankSize(0), m_bankType(BankType::UNDEFINED) {} + ~MemoryBank() { ReleaseBank(); } + + // creates a single basic memory bank with the option to create it at a system defined address or an address of choice + // There is not underlying track of the physical pages since this is a basic memory bank created through VirtualAlloc + bool CommitBank(size_t bankSize, uintptr_t baseAddressDesired = 0) + { + assert(!m_banks); + assert(!m_physicalPageArray); + try + { + // The basic memory bank only supports one bank, there is no sharing or rotating + m_numberOfBanks = 1; + m_banks = new void *[m_numberOfBanks]; + m_bankSize = bankSize; + // If a specific address is desired then the address range needs to be reserved first, it's not possible to reserve and commit in the same call + m_banks[0] = VirtualAlloc(reinterpret_cast (baseAddressDesired), bankSize, MEM_RESERVE, PAGE_READWRITE); + if (m_banks[0] == nullptr) + throw std::logic_error("Failed to reserve virtual memory when creating basic bank"); + + // Once the address is reserved it can be committed. + m_banks[0] = VirtualAlloc(m_banks[0], bankSize, MEM_COMMIT, PAGE_READWRITE); + if (m_banks[0] == nullptr) + throw std::logic_error("Failed to commit virtual memory when creating basic bank"); + } + catch (const std::exception& /*except*/) + { + return false; + } + m_bankType = BankType::BASIC_BANK; + return true; + } + + // Creates a shared memory bank. Each bank shares the same backing physical pages + // Shared banks can be created with adjacent virtual addresses. + // This is very useful for creating ring buffers without the need to break memory copies across boundaries. + bool CommitSharedBanks(size_t bankSize, size_t numberOfBanks = 1, bool adjacentBanks = false, uintptr_t baseAddressDesired = 0) + { + try + { + m_numberOfBanks = numberOfBanks; + m_numberOfPhysicalBanks = 1; + m_numberOfPhysicalPagesPerBank = bankSize / c_SIZE_PER_LARGE_PHYSICAL_PAGE; + m_physicalPageArray = new size_t *[1]; + m_physicalPageArray[0] = new size_t[m_numberOfPhysicalPagesPerBank]; + + size_t actualPagesAllocated = m_numberOfPhysicalPagesPerBank; + // The first step is to allocate the physical pages for the bank. + // Physical pages need to be allocated as either 64k or 4MB contiguous pages. However the OS will return them as an array of 64k page addresses + if (!AllocateTitlePhysicalPages(GetCurrentProcess(), bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, &actualPagesAllocated, m_physicalPageArray[0])) + { + delete[] m_physicalPageArray; + m_physicalPageArray = nullptr; + throw std::logic_error("Failed to allocate physical pages when creating shared banks"); + } + // It's possible when allocating physical pages that a smaller amount is returned. Consider this a failure for this sample + if (actualPagesAllocated < m_numberOfPhysicalPagesPerBank) + { + FreeTitlePhysicalPages(GetCurrentProcess(), actualPagesAllocated, m_physicalPageArray[0]); + m_physicalPageArray[0] = nullptr; + throw std::logic_error("Failed to allocate the requested number of physical pages when creating shared banks"); + } + m_bankSize = actualPagesAllocated * (bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? c_SIZE_PER_LARGE_PHYSICAL_PAGE : c_SIZE_PER_4MB_PHYSICAL_PAGE); + m_banks = new void *[m_numberOfBanks]; + memset(m_banks, 0, sizeof(uintptr_t) * m_numberOfBanks); + + // If the virtual banks have been requested to be adjacent then a single virtual address range needs to be reserved + if (adjacentBanks) + { + void *baseVirtualAddress; + // reserve the full virtual address range, it can be reserved at a known location or let the OS decide + baseVirtualAddress = VirtualAlloc(reinterpret_cast (baseAddressDesired), m_bankSize*m_numberOfBanks, MEM_RESERVE + (bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES), PAGE_READWRITE); + if (baseVirtualAddress == nullptr) + throw std::logic_error("Failed to reserve virtual memory when creating basic bank"); + for (uint32_t i = 0; i < m_numberOfBanks; i++) + { + void *bankVirtualAddress = (reinterpret_cast(baseVirtualAddress)) + (m_bankSize * i); + // map each of the physical pages into a section of the virtual address range, physical pages can be mapped multiple times + m_banks[i] = MapTitlePhysicalPages(bankVirtualAddress, m_numberOfPhysicalPagesPerBank, m_bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, PAGE_READWRITE, m_physicalPageArray[0]); + if (m_banks[i] == nullptr) + { + throw std::logic_error("Failed to map the physical pages when creating adjacent shared banks"); + } + } + } + else + { + for (uint32_t i = 0; i < m_numberOfBanks; i++) + { + m_banks[i] = MapTitlePhysicalPages(nullptr, m_numberOfPhysicalPagesPerBank, bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, PAGE_READWRITE, m_physicalPageArray[0]); + if (m_banks[i] == nullptr) + { + throw std::logic_error("Failed to map the physical pages when creating shared banks"); + } + } + } + } + catch (const std::exception& /*except*/) + { + ReleaseBank(); + return false; + } + m_bankType = BankType::SHARED_BANK; + return true; + } + + // Creates a set of banks that can be rotated or bank swapped, virtual addresses can be swapped between each physical bank + // This is very useful to remove memory copies in certain patterns + bool CommitRotateBanks(size_t bankSize, size_t numberOfBanks) + { + try + { + m_numberOfBanks = numberOfBanks; + m_numberOfPhysicalBanks = numberOfBanks; + m_numberOfPhysicalPagesPerBank = bankSize / c_SIZE_PER_LARGE_PHYSICAL_PAGE; + m_physicalPageArray = new size_t *[m_numberOfPhysicalBanks]; + memset(m_physicalPageArray, 0, sizeof(uintptr_t) * m_numberOfPhysicalBanks); + + for (uint32_t i = 0; i < m_numberOfBanks; i++) + { + size_t actualPagesAllocated = m_numberOfPhysicalPagesPerBank; + m_physicalPageArray[i] = new size_t[m_numberOfPhysicalPagesPerBank]; + // The first step is to allocate the physical pages for the bank. + // Physical pages need to be allocated as either 64k or 4MB contiguous pages. However the OS will return them as an array of 64k page addresses + if (!AllocateTitlePhysicalPages(GetCurrentProcess(), bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, &actualPagesAllocated, m_physicalPageArray[i])) + { + throw std::logic_error("Failed to allocate physical pages when creating rotating banks"); + } + // It's possible when allocating physical pages that a smaller amount is returned. Consider this a failure for this sample + if (actualPagesAllocated < m_numberOfPhysicalPagesPerBank) + { + FreeTitlePhysicalPages(GetCurrentProcess(), actualPagesAllocated, m_physicalPageArray[i]); + m_physicalPageArray[i] = nullptr; + throw std::logic_error("Failed to allocate requested number of physical pages when creating rotating banks"); + } + m_bankSize = actualPagesAllocated * (bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? c_SIZE_PER_LARGE_PHYSICAL_PAGE : c_SIZE_PER_4MB_PHYSICAL_PAGE); + } + m_banks = new void *[m_numberOfBanks]; + for (uint32_t i = 0; i < m_numberOfBanks; i++) + { + // allocate a virtual address range for each physical bank + m_banks[i] = MapTitlePhysicalPages(nullptr, m_numberOfPhysicalPagesPerBank, bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, PAGE_READWRITE, m_physicalPageArray[i]); + if (m_banks[i] == nullptr) + throw std::logic_error("Failed to map the physical pages when creating rotating banks"); + } + } + catch (const std::exception& /*except*/) + { + ReleaseBank(); + return false; + } + m_bankType = BankType::ROTATE_BANK; + return true; + } + + void ReleaseBank() + { + if (m_banks) + { + for (size_t i = 0; i < m_numberOfBanks; i++) + { + if (m_banks[i]) // it's possible for this to fail for adjacent pages, however they are all released with the first page + VirtualFree(m_banks[i], 0, MEM_RELEASE); + } + delete[] m_banks; + m_banks = nullptr; + } + + if (m_physicalPageArray) + { + for (size_t i = 0; i < m_numberOfPhysicalBanks; i++) + { + if (m_physicalPageArray[i]) + FreeTitlePhysicalPages(GetCurrentProcess(), m_numberOfPhysicalPagesPerBank, m_physicalPageArray[i]); + } + delete[] m_physicalPageArray; + m_physicalPageArray = nullptr; + } + } + + // swap the virtual address for two physical banks + bool SwapBanks(size_t bankIndex1, size_t bankIndex2) + { + assert(m_bankType == BankType::ROTATE_BANK); + assert(bankIndex1 <= m_numberOfBanks); + assert(bankIndex2 <= m_numberOfBanks); + try + { + void *bankAddress1 = m_banks[bankIndex1]; + void *bankAddress2 = m_banks[bankIndex2]; + // The first step is to release the virtual addresses used by the two physical banks + // This does not actually release the physical memory because it was allocated through AllocateTitlePhysicalPages + // Since the physical address is still allocated it's contents are not changed + if (!VirtualFree(bankAddress1, 0, MEM_RELEASE)) + throw std::logic_error("Failed to release bank 1 in swap banks"); + if (!VirtualFree(bankAddress2, 0, MEM_RELEASE)) + throw std::logic_error("Failed to release bank 2 in swap banks"); + for (uint32_t i = 0; i < m_numberOfPhysicalPagesPerBank; i++) + { + std::swap(m_physicalPageArray[bankIndex1][i], m_physicalPageArray[bankIndex2][i]); + } + + // Remap the two physical banks with the swapped virtual addresses. + void *newBank1Address = MapTitlePhysicalPages(bankAddress1, m_numberOfPhysicalPagesPerBank, m_bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, PAGE_READWRITE, m_physicalPageArray[bankIndex1]); + if (newBank1Address != m_banks[bankIndex1]) + throw std::logic_error("Failed to remap bank 1 in swap banks"); + void *newBank2Address = MapTitlePhysicalPages(bankAddress2, m_numberOfPhysicalPagesPerBank, m_bankSize < c_SIZE_PER_4MB_PHYSICAL_PAGE ? MEM_LARGE_PAGES : MEM_4MB_PAGES, PAGE_READWRITE, m_physicalPageArray[bankIndex2]); + if (newBank2Address != m_banks[bankIndex2]) + throw std::logic_error("Failed to remap bank 2 in swap banks"); + } + catch (const std::exception /*except*/) + { + ReleaseBank(); + return false; + } + return true; + } + + // In many cases it's useful to convert a block of memory to read-only + // This is useful for static data that is created once and then doesn't change throughout it's lifetime + // Any attempt to change the memory will result in an immediate exception + // When using shared banks (multiple virtual addresses to the same physical address) each virtual address can have different protection flags + // This means when accessing memory through one address it's read/write, however it's read-only through a different address. + bool LockBank(size_t bankIndex = SIZE_MAX) // SIZE_MAX means lock all banks + { + assert(m_banks); + if (bankIndex == SIZE_MAX) + { + bool toret = true; + for (size_t i = 0; i < m_numberOfBanks; i++) + { + DWORD oldProtect; + if (m_banks[i]) + { + if (VirtualProtect(m_banks[i], m_bankSize, PAGE_READONLY, &oldProtect) == 0) + toret = false; + } + } + return toret; + } + else + { + assert(bankIndex <= m_numberOfBanks); + DWORD oldProtect; + if (m_banks[bankIndex] == nullptr) + return false; + return VirtualProtect(m_banks[bankIndex], m_bankSize, PAGE_READONLY, &oldProtect) != 0; + } + } + + operator void * () const { assert(m_banks); return m_banks[0]; } + void *get(size_t bankIndex = 0) const { assert(bankIndex <= m_numberOfBanks); return m_banks[bankIndex]; } +}; \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/MemoryBanks.cpp b/XDKSamples/System/MemoryBanks/MemoryBanks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39a27ca67746f0982b8fe7afa8048ba2162df546 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryBanks.cpp @@ -0,0 +1,303 @@ +//-------------------------------------------------------------------------------------- +// MemoryBanks.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryBanks.h" + +#include "ATGColors.h" +#include "ControllerFont.h" +#include "MemoryDemo.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_randomBankStatus = TestStatus::TEST_NOT_RUN; + m_fixedBankStatus = TestStatus::TEST_NOT_RUN; + m_readOnlyBankStatus = TestStatus::TEST_NOT_RUN; + m_bankSwitchingStatus = TestStatus::TEST_NOT_RUN; + m_sharedAddressStatus = TestStatus::TEST_NOT_RUN; + + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& /*timer*/) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + if (m_frame == 1) + { + // Create the two data files that are used by the sample + m_memoryBankDemo.CreateFixedTestDataFile(); + m_memoryBankDemo.CreateRandomTestDataFile(); + } + else if (m_frame > 1) + { + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsAPressed()) + { + m_randomBankStatus = m_memoryBankDemo.RunTest(ATG::MemoryBankDemoTests::MEMORY_BANK_RANDOM_ADDRESS) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (pad.IsBPressed()) + { + m_fixedBankStatus = m_memoryBankDemo.RunTest(ATG::MemoryBankDemoTests::MEMORY_BANK_FIXED_ADDRESS) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (pad.IsXPressed()) + { + m_bankSwitchingStatus = m_memoryBankDemo.RunTest(ATG::MemoryBankDemoTests::BANK_SWITCHING) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (pad.IsYPressed()) + { + m_sharedAddressStatus = m_memoryBankDemo.RunTest(ATG::MemoryBankDemoTests::SHARED_ADDRESS) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + if (pad.IsLeftShoulderPressed()) + { + m_readOnlyBankStatus = m_memoryBankDemo.RunTest(ATG::MemoryBankDemoTests::READ_ONLY_MEMORY_BANK) ? TestStatus::TEST_SUCCESS : TestStatus::TEST_FAILURE; + } + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(1920, 1080); + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_spriteBatch->Begin(); + m_spriteBatch->Draw(m_background.Get(), m_deviceResources->GetOutputSize()); + + DrawStatusString(L"[A]", L"Random Address", m_randomBankStatus, pos); + DrawHelpText(pos, ATG::MemoryBankDemoTests::MEMORY_BANK_RANDOM_ADDRESS); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[B]", L"Fixed Address", m_fixedBankStatus, pos); + DrawHelpText(pos, ATG::MemoryBankDemoTests::MEMORY_BANK_FIXED_ADDRESS); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[X]", L"Bank Switching", m_bankSwitchingStatus, pos); + DrawHelpText(pos, ATG::MemoryBankDemoTests::BANK_SWITCHING); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[Y]", L"Shared Address", m_sharedAddressStatus, pos); + DrawHelpText(pos, ATG::MemoryBankDemoTests::SHARED_ADDRESS); + pos.y += m_font->GetLineSpacing() * 3; + + DrawStatusString(L"[LB]", L"Read Only Address", m_readOnlyBankStatus, pos); + DrawHelpText(pos, ATG::MemoryBankDemoTests::READ_ONLY_MEMORY_BANK); + + m_spriteBatch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +void Sample::DrawStatusString(const std::wstring& button, const std::wstring& testName, TestStatus status, XMFLOAT2& pos) +{ + RECT stringBounds; + std::wstring outputString; + std::wstring resultString; + XMVECTORF32 resultColor = ATG::Colors::OffWhite; + outputString = L"Press "; + outputString += button; + outputString += L" to run "; + outputString += testName; + outputString += L" Test: "; + switch (status) + { + case TestStatus::TEST_NOT_RUN: + resultString += L"not run yet"; + break; + case TestStatus::TEST_SUCCESS: + resultString += L"success"; + resultColor = ATG::Colors::Green; + break; + case TestStatus::TEST_FAILURE: + resultString += L"failure"; + resultColor = ATG::Colors::Orange; + break; + } + DX::DrawControllerString(m_spriteBatch.get(), m_font.get(), m_ctrlFont.get(), outputString.c_str(), pos); + stringBounds = DX::MeasureControllerDrawBounds(m_font.get(), m_ctrlFont.get(), outputString.c_str(), pos); + pos.x += (stringBounds.right - stringBounds.left); + m_font->DrawString(m_spriteBatch.get(), resultString.c_str(), pos, resultColor); + pos.x -= (stringBounds.right - stringBounds.left); +} + +void Sample::DrawHelpText(DirectX::XMFLOAT2& pos, ATG::MemoryBankDemoTests whichTest) +{ + static const wchar_t *helpText[] = { + L" Baseline for all demonstrations.", + L" Allocates a block of memory through VirtualAlloc and then reads a binary tree into the memory block.", + L" The pointers within the binary tree are then fixed up to match the address of the memory block.", + L" Memory block allocated at a predetermined virtual address.", + L" The memory block is allocated at a virtual address that doesn't change between runs of the title.", + L" This removes the need for the fix up of the pointers in the binary tree, the values can be saved to disk directly.", + L" Two memory blocks that can have their virtual address swapped", + L" Two memory banks are created through VirtualAlloc, Bank A and Bank B.", + L" The banks then have their virtual address swapped. The virtual address of bank A now points to the physical address of Bank B, and vice versa.", + L" Two memory banks that have their own unique virtual addresses, but a shared physical address.", + L" One physical memory bank is created through AllocateTitlePhysicalPages.", + L" The single physical bank is then mapped to two virtual addresses using MapTitlePhysicalPages.", + L" Changing the protection scheme of a memory bank to read-only", + L" Uses the shared setup with one physical bank mapped to two virtual addresses, Bank A and Bank B", + L" Bank A is set to read-only while Bank B stays as read-write. A protection fault is generated when writing through Bank A", + }; + uint32_t startIndex(0); + switch (whichTest) + { + case ATG::MemoryBankDemoTests::MEMORY_BANK_RANDOM_ADDRESS: + startIndex = 0; + break; + case ATG::MemoryBankDemoTests::MEMORY_BANK_FIXED_ADDRESS: + startIndex = 3; + break; + case ATG::MemoryBankDemoTests::BANK_SWITCHING: + startIndex = 6; + break; + case ATG::MemoryBankDemoTests::SHARED_ADDRESS: + startIndex = 9; + break; + case ATG::MemoryBankDemoTests::READ_ONLY_MEMORY_BANK: + startIndex = 12; + break; + } + for (uint32_t i = 0; i < 3; i++) + { + pos.y += m_font->GetLineSpacing() * 1.1f; + m_font->DrawString(m_spriteBatch.get(), helpText[i + startIndex], pos); + } +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneController.spritefont"); + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/System/MemoryBanks/MemoryBanks.h b/XDKSamples/System/MemoryBanks/MemoryBanks.h new file mode 100644 index 0000000000000000000000000000000000000000..9084697564fa60f2c2c7e4d37249f845ff25af2f --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryBanks.h @@ -0,0 +1,76 @@ +//-------------------------------------------------------------------------------------- +// MemoryBanks.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "MemoryDemo.h" + +// A basic sample implementation that creates a D3D11 device with a render loop. +// The sample can run five different tests of the memory bank code showing various ways to create and interact with memory +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Main class driving the demo code + ATG::MemoryDemo m_memoryBankDemo; + enum class TestStatus + { + TEST_NOT_RUN, + TEST_SUCCESS, + TEST_FAILURE, + }; + TestStatus m_randomBankStatus; + TestStatus m_fixedBankStatus; + TestStatus m_readOnlyBankStatus; + TestStatus m_bankSwitchingStatus; + TestStatus m_sharedAddressStatus; + + void DrawStatusString(const std::wstring& button, const std::wstring& testName, TestStatus status, DirectX::XMFLOAT2& pos); + void DrawHelpText(DirectX::XMFLOAT2& pos, ATG::MemoryBankDemoTests); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + Microsoft::WRL::ComPtr m_background; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + std::unique_ptr m_ctrlFont; +}; diff --git a/XDKSamples/System/MemoryBanks/MemoryBanks.sln b/XDKSamples/System/MemoryBanks/MemoryBanks.sln new file mode 100644 index 0000000000000000000000000000000000000000..2bbca11e1e17ef1a8f5c3071db650e87ef96c747 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryBanks.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemoryBanks", "MemoryBanks.vcxproj", "{9B329340-9E4F-47B1-8F80-B41DAC9D66EF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Debug|Durango.ActiveCfg = Debug|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Debug|Durango.Build.0 = Debug|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Debug|Durango.Deploy.0 = Debug|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Profile|Durango.ActiveCfg = Profile|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Profile|Durango.Build.0 = Profile|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Profile|Durango.Deploy.0 = Profile|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Release|Durango.ActiveCfg = Release|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Release|Durango.Build.0 = Release|Durango + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF}.Release|Durango.Deploy.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/MemoryBanks/MemoryBanks.vcxproj b/XDKSamples/System/MemoryBanks/MemoryBanks.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..847c808c236aa546efce704be0a90310c86c2090 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryBanks.vcxproj @@ -0,0 +1,230 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + MemoryBanks + {9B329340-9E4F-47B1-8F80-B41DAC9D66EF} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + Designer + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/MemoryBanks.vcxproj.filters b/XDKSamples/System/MemoryBanks/MemoryBanks.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..c0bfc6bfd11087f833fe8f94064a007aa45613c4 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryBanks.vcxproj.filters @@ -0,0 +1,82 @@ + + + + + fb58f553-b00c-4c88-b083-c98f4642020d + + + a5ea1436-c3af-47bc-b18a-d6e163475e95 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {8b89c340-d321-4911-b56e-e7ec6f17cdea} + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + + + + ATG Tool Kit + + + + + + + Common + + + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/MemoryDemo.cpp b/XDKSamples/System/MemoryBanks/MemoryDemo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..700218fffc76d3060c5bf85fb959135232bdee66 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryDemo.cpp @@ -0,0 +1,142 @@ +//-------------------------------------------------------------------------------------- +// MemoryDemo.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryDemo.h" + +namespace ATG +{ + MemoryDemo::MemoryDemo() : + m_rootNode(nullptr) + { + } + MemoryDemo::~MemoryDemo() + { + } + + bool MemoryDemo::RunTest(MemoryBankDemoTests whichTest) + { + __try // With all of the memory access in these tests it's possible for a bad pointer dereference + { // we are building with /EHsc which means C++ try/catch will not catch OS exceptions like null pointer dereferences. + // these types of exceptions require SEH to catch + switch (whichTest) + { + case MemoryBankDemoTests::MEMORY_BANK_RANDOM_ADDRESS: + return TestRandomAddress(); + case MemoryBankDemoTests::MEMORY_BANK_FIXED_ADDRESS: + return TestFixedAddress(); + case MemoryBankDemoTests::READ_ONLY_MEMORY_BANK: + return TestReadOnlyBank(); + case MemoryBankDemoTests::BANK_SWITCHING: + return TestBankSwitching(); + case MemoryBankDemoTests::SHARED_ADDRESS: + return TestSharedAddress(); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + switch (whichTest) + { + case MemoryBankDemoTests::MEMORY_BANK_RANDOM_ADDRESS: + OutputDebugStringA("Testing random address bank threw an exception\n"); + break; + case MemoryBankDemoTests::MEMORY_BANK_FIXED_ADDRESS: + OutputDebugStringA("Testing fixed address bank threw an exception\n"); + break; + case MemoryBankDemoTests::READ_ONLY_MEMORY_BANK: + OutputDebugStringA("Testing read only bank threw an exception\n"); + break; + case MemoryBankDemoTests::BANK_SWITCHING: + OutputDebugStringA("Testing bank switching threw an exception\n"); + break; + case MemoryBankDemoTests::SHARED_ADDRESS: + OutputDebugStringA("Testing shared address bank threw an exception\n"); + break; + } + } + return false; + } + + // run through the entire binary tree validating all of the data + bool MemoryDemo::ValidateData(const TestData *curNode, bool isLeft, uint32_t treeLevel) + { + __try // There could be random pointer dereferencing in here on bad data + { // we are building with /EHsc which means C++ try/catch will not catch OS exceptions like null pointer dereferences. + // these types of exceptions require SEH to catch + if (curNode->m_isLeftNode != isLeft) + return false; + if (curNode->m_treeLevel != treeLevel) + return false; + if (curNode->m_left) + { + if (!ValidateData(curNode->m_left, true, treeLevel + 1)) + return false; + } + if (curNode->m_right) + { + if (!ValidateData(curNode->m_right, false, treeLevel + 1)) + return false; + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + OutputDebugStringA("Validating data threw an exception\n"); + return false; + } + return true; + } + + // go through each node and create new random data in the node + bool MemoryDemo::ShuffleRandomData(TestData *curNode) + { + __try // There could be random pointer dereferencing in here on bad data + { // we are building with /EHsc which means C++ try/catch will not catch OS exceptions like null pointer dereferences. + // these types of exceptions require SEH to catch + curNode->m_randomData = std::rand(); + if ((curNode->m_left) && !ShuffleRandomData(curNode->m_left)) + return false; + if ((curNode->m_right) && !ShuffleRandomData(curNode->m_right)) + return false; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + OutputDebugStringA("shuffling random data threw an exception\n"); + return false; + } + return true; + } + + // recursively create the binary tree + bool MemoryDemo::InternalCreateTestData(TestData *curNode, uint32_t curTreeLevel, TestData* stackAllocator, size_t& stackAllocatorIndex) + { + curNode->m_randomData = std::rand(); + if (curTreeLevel == c_maxTestDataTreeLevel) + { + curNode->m_leftIndex = curNode->m_rightIndex = SIZE_MAX; + curNode->m_left = curNode->m_right = nullptr; + return true; + } + + TestData *leftNode = &(stackAllocator[stackAllocatorIndex++]); + leftNode->m_isLeftNode = true; + leftNode->m_treeLevel = curTreeLevel; + curNode->m_leftIndex = stackAllocatorIndex - 1; + + TestData *rightNode = &(stackAllocator[stackAllocatorIndex++]); + rightNode->m_isLeftNode = false; + rightNode->m_treeLevel = curTreeLevel; + curNode->m_rightIndex = stackAllocatorIndex - 1; + + if (!InternalCreateTestData(leftNode, curTreeLevel + 1, stackAllocator, stackAllocatorIndex)) + return false; + if (!InternalCreateTestData(rightNode, curTreeLevel + 1, stackAllocator, stackAllocatorIndex)) + return false; + curNode->m_left = leftNode; + curNode->m_right = rightNode; + return true; + } +} diff --git a/XDKSamples/System/MemoryBanks/MemoryDemo.h b/XDKSamples/System/MemoryBanks/MemoryDemo.h new file mode 100644 index 0000000000000000000000000000000000000000..ad29ba755db4f2eab2b902b4297bcbfe0a62ed81 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/MemoryDemo.h @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------------------- +// MemoryDemo.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "MemoryBank.h" + +namespace ATG +{ + // Basic binary tree being used as test data + struct TestData + { + bool m_isLeftNode; // flag used during validation + uint32_t m_randomData; // Just a block of random data used during validation, used as a scratch space for writing + uint32_t m_treeLevel; // The level within the tree for this node + size_t m_leftIndex, m_rightIndex; // Index within the memory block for the left and right nodes, used to fixup addresses when loaded from disk + TestData *m_left, *m_right; // Pointers to the left and right node + }; + + enum class MemoryBankDemoTests + { + MEMORY_BANK_RANDOM_ADDRESS, // Standard block of memory where the OS decides the address + MEMORY_BANK_FIXED_ADDRESS, // Block of memory where the title chooses the base address for the block of memory + BANK_SWITCHING, // Several blocks of memory that are page swapped and validated + SHARED_ADDRESS, // A single block of physical memory with adjacent virtual addresses used as a ring buffer + READ_ONLY_MEMORY_BANK, // A block of memory where the sample attempts to write to read-only memory + }; + + class MemoryDemo + { + private: + static const size_t c_memoryBankSize = 128 * 1024; + static const uint32_t c_maxTestDataTreeLevel = 10; + static const size_t c_testDataAllocatorSize = 1 << c_maxTestDataTreeLevel; + static char *c_fixedTestDataFilename; + static char *c_randomTestDataFilename; + + MemoryBank m_memoryBank; + TestData *m_rootNode; + + bool TestRandomAddress(); + bool TestFixedAddress(); + bool TestReadOnlyBank(); + bool TestBankSwitching(); + bool TestSharedAddress(); + bool ValidateData(const TestData *curNode, bool isLeft, uint32_t treeLevel); + bool ShuffleRandomData(TestData *curNode); + + bool InternalCreateTestData(TestData *curNode, uint32_t curTreeLevel, TestData* stackAllocatorBase, size_t& stackAllocatorIndex); + + bool LoadFixedAddress(); + bool LoadRandomAddress(); + void FixupRandomAddresses(TestData *curNode, TestData* stackAllocatorBase); + + public: + MemoryDemo(); + ~MemoryDemo(); + + bool CreateFixedTestDataFile(); + bool CreateRandomTestDataFile(); + + MemoryDemo(const MemoryDemo&) = delete; + MemoryDemo& operator=(const MemoryDemo&) = delete; + MemoryDemo(MemoryDemo&& rhs) = default; + + bool RunTest(MemoryBankDemoTests whichTest); + }; +} diff --git a/XDKSamples/System/MemoryBanks/Package.appxmanifest b/XDKSamples/System/MemoryBanks/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..0d2d1172d5f6651ea1c64fbd2a3741b3d9b71a14 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/Package.appxmanifest @@ -0,0 +1,50 @@ + + + + + + + MemoryBanks + Xbox Advanced Technology Group + Assets\StoreLogo.png + MemoryBanks + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/MemoryBanks/RandomMemory.cpp b/XDKSamples/System/MemoryBanks/RandomMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bff200e794f30db3609f726dc95d7073ee920b43 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/RandomMemory.cpp @@ -0,0 +1,123 @@ +//-------------------------------------------------------------------------------------- +// RandomMemory.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryDemo.h" + +// The code related to testing the random address sample +namespace ATG +{ + char *MemoryDemo::c_randomTestDataFilename = "t:\\staticMemoryRandomTestData.dat"; + + // Load the binary tree data from disk and then validate the data + // The binary tree is allocated from the single bank allocated at a random address + bool MemoryDemo::TestRandomAddress() + { + try + { + m_memoryBank.ReleaseBank(); + if (!LoadRandomAddress()) + throw std::logic_error("Unable to load random address data"); + if (!ValidateData(m_rootNode, false, 0)) + throw std::logic_error("Failed to validate random address data"); + } + catch (const std::logic_error what) + { + OutputDebugStringA(what.what()); + m_memoryBank.ReleaseBank(); + return false; + } + return true; + } + + // Since the address is random all of the internal pointers need to be fixed after loading the data from disk + // The index within the binary tree node is the index into the memory bank + void MemoryDemo::FixupRandomAddresses(TestData *curNode, TestData* memoryBase) + { + if (curNode->m_leftIndex != SIZE_MAX) + curNode->m_left = &(memoryBase[curNode->m_leftIndex]); + else + curNode->m_left = nullptr; + + if (curNode->m_rightIndex != SIZE_MAX) + curNode->m_right = &(memoryBase[curNode->m_rightIndex]); + else + curNode->m_right = nullptr; + + if (curNode->m_left) + FixupRandomAddresses(curNode->m_left, memoryBase); + if (curNode->m_right) + FixupRandomAddresses(curNode->m_right, memoryBase); + } + + // load the binary tree from disk, since the tree is allocated from one memory bank a single read from disk is enough + bool MemoryDemo::LoadRandomAddress() + { + FILE *file = nullptr; + try + { + if (!m_memoryBank.CommitBank(c_testDataAllocatorSize * sizeof(TestData))) + throw std::logic_error("unable to commit memory at random memory address\n"); + + fopen_s(&file, c_randomTestDataFilename, "rb"); + if (!file) + throw std::logic_error("unable to open data file\n"); + if (fread(m_memoryBank, sizeof(TestData), c_testDataAllocatorSize, file) != c_testDataAllocatorSize) + throw std::logic_error("unable to read data file\n"); + fclose(file); + + // need to fix up the addresses now + m_rootNode = reinterpret_cast (m_memoryBank.get()); + FixupRandomAddresses(m_rootNode, m_rootNode); + } + catch (const std::exception& what) + { + OutputDebugStringA(what.what()); + if (file) + fclose(file); + m_memoryBank.ReleaseBank(); + m_rootNode = nullptr; + return false; + } + return true; + } + + bool MemoryDemo::CreateRandomTestDataFile() + { + FILE *file = nullptr; + try + { + size_t stackAllocatorIndex = 0; + std::unique_ptr stackAllocator(new TestData[c_testDataAllocatorSize]); + if (!stackAllocator) + throw std::logic_error("unable to allocate memory for random test data"); + + TestData *rootNode = &(stackAllocator[stackAllocatorIndex++]); + rootNode->m_isLeftNode = false; + rootNode->m_treeLevel = 0; + + if (!InternalCreateTestData(rootNode, 1, stackAllocator.get(), stackAllocatorIndex)) + throw std::logic_error("unable to create test tree\n"); + + fopen_s(&file, c_randomTestDataFilename, "wb"); + if (!file) + throw std::logic_error("unable to create data file\n"); + if (fwrite(stackAllocator.get(), sizeof(TestData), c_testDataAllocatorSize, file) != c_testDataAllocatorSize) + throw std::logic_error("unable to save data file\n"); + fclose(file); + } + catch (const std::exception& what) + { + OutputDebugStringA(what.what()); + if (file) + fclose(file); + return false; + } + + return true; + } +} diff --git a/XDKSamples/System/MemoryBanks/ReadOnlyMemory.cpp b/XDKSamples/System/MemoryBanks/ReadOnlyMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d683be17df5d6164ed61cbec9c1acd5c6364906 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/ReadOnlyMemory.cpp @@ -0,0 +1,50 @@ +//-------------------------------------------------------------------------------------- +// ReadOnlyMemory.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryDemo.h" + +// The code related to testing the read only address sample +namespace ATG +{ + bool MemoryDemo::TestReadOnlyBank() + { + m_memoryBank.ReleaseBank(); + if (!m_memoryBank.CommitSharedBanks(c_memoryBankSize, 2)) + return false; + m_memoryBank.LockBank(1); + __try // This block should not throw an exception since the data should be writeable. + { // we are building with /EHsc which means C++ try/catch will not catch OS exceptions like null pointer dereferences. + // these types of exceptions require SEH to catch + memset(m_memoryBank.get(0), 1, c_memoryBankSize); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + m_memoryBank.ReleaseBank(); + OutputDebugStringA("trying to write to read-write block of shared bank failed, it should not\n"); + return false; + } + + bool successfullTest = false; + __try // This should throw an exception since the data block is now read-only + { // we are building with /EHsc which means C++ try/catch will not catch OS exceptions + // like this write access violation, so we use SEH instead to catch it + char *bankBaseAddress = static_cast (m_memoryBank.get(1)); + for (uint32_t i = 0; i < c_memoryBankSize; i++) + { + bankBaseAddress[i] = 1; //should throw access violation exception + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + successfullTest = true; + } + if (!successfullTest) + throw std::logic_error("trying to write to read-only block of shared bank succeeded which is should not"); + return true; + } +} diff --git a/XDKSamples/System/MemoryBanks/Readme.docx b/XDKSamples/System/MemoryBanks/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..3f7e0630ada17aaffbebd72969a06e6c729e511c Binary files /dev/null and b/XDKSamples/System/MemoryBanks/Readme.docx differ diff --git a/XDKSamples/System/MemoryBanks/SharedMemory.cpp b/XDKSamples/System/MemoryBanks/SharedMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ac0f0429daca0b706edfca41aadbc9047467feb --- /dev/null +++ b/XDKSamples/System/MemoryBanks/SharedMemory.cpp @@ -0,0 +1,54 @@ +//-------------------------------------------------------------------------------------- +// SharedMemory.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "MemoryDemo.h" + +// The code related to testing the shared address sample +namespace ATG +{ + bool MemoryDemo::TestSharedAddress() + { + __try // There could be random pointer dereferencing in here on bad data + { // we are building with /EHsc which means C++ try/catch will not catch OS exceptions like null pointer dereferences. + // these types of exceptions require SEH to catch + m_memoryBank.ReleaseBank(); + m_memoryBank.CommitSharedBanks(c_memoryBankSize, 2, false); + memset(m_memoryBank.get(0), 1, c_memoryBankSize); + if (memcmp(m_memoryBank.get(0), m_memoryBank.get(1), c_memoryBankSize) != 0) + { + OutputDebugStringA("shared memory banks are not equal\n"); + return false; + } + + m_memoryBank.ReleaseBank(); + m_memoryBank.CommitSharedBanks(c_memoryBankSize * sizeof(uint32_t), 2, true); + + uint32_t *baseAddress = reinterpret_cast (m_memoryBank.get(0)); + //write to memory so that is writes off the end of the buffer and into start due to the shared adjacent addresses + for (uint32_t i = 0; i < c_memoryBankSize; i++) + { + baseAddress[i + (c_memoryBankSize / 2)] = i; + } + for (uint32_t i = 0; i < c_memoryBankSize; i++) + { + if (baseAddress[i] != ((i + (c_memoryBankSize / 2)) % c_memoryBankSize)) + { + OutputDebugStringA("Testing adjacent shared memory banks did not wrap correctly\n"); + return false; + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + OutputDebugStringA("Testing shared memory banks threw an exception\n"); + return false; + } + + return true; + } +} diff --git a/XDKSamples/System/MemoryBanks/StepTimer.h b/XDKSamples/System/MemoryBanks/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/MemoryBanks/Telemetry.h b/XDKSamples/System/MemoryBanks/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/MemoryBanks/pch.cpp b/XDKSamples/System/MemoryBanks/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/MemoryBanks/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/MemoryBanks/pch.h b/XDKSamples/System/MemoryBanks/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..d0c83a4801875641160ce831e6aeedbc9d5b4791 --- /dev/null +++ b/XDKSamples/System/MemoryBanks/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif + +#include +#include +#include +#include +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "SimpleMath.h" +#include "DDSTextureLoader.h" + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization.sln b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization.sln new file mode 100644 index 0000000000000000000000000000000000000000..e24f228732be12d9f1169ac76482c19e3dec2d06 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NLSAndLocalization", "NLSAndLocalization\NLSAndLocalization.vcxproj", "{53CC0A60-33E5-4059-9DB1-647B9A94C2C4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Debug|Durango.ActiveCfg = Debug|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Debug|Durango.Build.0 = Debug|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Debug|Durango.Deploy.0 = Debug|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Profile|Durango.ActiveCfg = Profile|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Profile|Durango.Build.0 = Profile|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Profile|Durango.Deploy.0 = Profile|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Release|Durango.ActiveCfg = Release|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Release|Durango.Build.0 = Release|Durango + {53CC0A60-33E5-4059-9DB1-647B9A94C2C4}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/de-DE/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/de-DE/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..5d056013e0bb5570c08602e335916464c0631c27 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/de-DE/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en-GB/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en-GB/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..2242110c7eded048787421dc2f325d6b9bb67e10 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en-GB/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en-US/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en-US/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..f06ee74955347aff19ae33c57b69372b75190716 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en-US/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..52c0ed3b1a8ae2132b1db81fc7a595b0b61fb661 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/en/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/fr-FR/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/fr-FR/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..5e14feee7e8ce0d9d8825e59bae8c1cc4506729c Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/fr-FR/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/fr/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/fr/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..acb7331b80e77128993374140bfe037a4a549f69 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/fr/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/ja-JP/Image.dds b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/ja-JP/Image.dds new file mode 100644 index 0000000000000000000000000000000000000000..cff8d2ad8f67919c2cb0ec78d4d27da78dd96aeb Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Images/ja-JP/Image.dds differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Logo.png b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Logo.png differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/de-DE.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/de-DE.resources new file mode 100644 index 0000000000000000000000000000000000000000..1e6e8a6afb8c9af8b2535bdb7aa8bc4bc136f3ab Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/de-DE.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en-GB.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en-GB.resources new file mode 100644 index 0000000000000000000000000000000000000000..2e853322fdc573be836c69d50242ab22fea40666 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en-GB.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en-US.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en-US.resources new file mode 100644 index 0000000000000000000000000000000000000000..d2c3e5cbafa8320e8b1df39b7fecff12ccf9a123 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en-US.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en.resources new file mode 100644 index 0000000000000000000000000000000000000000..02bf72e820555cacceb6c4e232d6628fada61d61 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/en.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/fr-FR.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/fr-FR.resources new file mode 100644 index 0000000000000000000000000000000000000000..f809793754bcc1fec99cf9a3724a5e475954f676 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/fr-FR.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/fr.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/fr.resources new file mode 100644 index 0000000000000000000000000000000000000000..ff58ed00b7b794f810e4d7e1200499f2c20a0404 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/fr.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/ja-JP.resources b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/ja-JP.resources new file mode 100644 index 0000000000000000000000000000000000000000..a555f0cb152c18cc4d24acf3e83d285f1b025f6c Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/Resources/ja-JP.resources differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/SmallLogo.png b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/SplashScreen.png b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/StoreLogo.png b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/WideLogo.png b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Assets/WideLogo.png differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/DeviceResources.cpp b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9ffbb6b9d065941a609390393833d7513777f1e --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/DeviceResources.cpp @@ -0,0 +1,222 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/DeviceResources.h b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..0c4c4f36247f9a8ea4367769d8d5b92726f9fe3e --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/DeviceResources.h @@ -0,0 +1,70 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Main.cpp b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5ac7d82b64632b839e8d4c0bb4d178ebee128de --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "NLSAndLocalization.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.cpp b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..538be5ee1aa46c4bc150705a718a5ff274f11129 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.cpp @@ -0,0 +1,348 @@ +//-------------------------------------------------------------------------------------- +// NLSAndLocalization.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "NLSAndLocalization.h" + +#include "ATGColors.h" + +extern void ExitSample(); + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(); + m_textConsole = std::make_unique(); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + int retVal = GetUserDefaultLocaleName(m_localeName, ARRAYSIZE(m_localeName)); + if (retVal == 0) + throw std::exception("Failed to get locale in CreateDeviceDependenciesResources"); + swprintf_s(m_imagePrepend, _countof(m_imagePrepend), L"Assets\\Images\\%s\\", m_localeName); + swprintf_s(m_resFileName, _countof(m_resFileName), L"Assets\\Resources\\%s.resources", m_localeName); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + InitializeLocalization(); +} + +void Sample::InitializeLocalization() +{ + + m_textConsole->Format(L"******* Using the NLS APIs *******\n"); + m_textConsole->Format(L"Note: All the strings except the ones with\nthe IDs in the Localization section\nare hard coded in English (not localized)\n\n"); + + // Get Package Details using the Package Id + Windows::ApplicationModel::Package^ package = Windows::ApplicationModel::Package::Current; + Windows::ApplicationModel::PackageId^ packageId = package->Id; + m_textConsole->Format(L"The Package Full Name is: %s\n", packageId->FullName->Data()); + + // Get the locale name for the system using GetUserDefaultLocaleName(). This will return the locale selected through the + // Settings app only if that locale has been added to the Resources section of the application's package manifest. + // In case the resource is absent fron the manifest, this API will return the first locale in the Resource Language. + wchar_t userLocaleName[LOCALE_NAME_MAX_LENGTH] = { L'\0' }; + wchar_t message[1024] = { L'\0' }; + int retVal = GetUserDefaultLocaleName(userLocaleName, ARRAYSIZE(userLocaleName)); + if (FunctionSucceeded(retVal, L"GetUserDefaultLocaleName")) + { + swprintf_s(message, L"GetUserDefaultLocaleName succeeded: %s\n", userLocaleName); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("GetUserDefaultLocaleName failed!"); + } + + unsigned long lcid = LocaleNameToLCID(userLocaleName, 0); + unsigned short primary = 0, sublang = 0; + if (FunctionSucceeded(lcid, L"LocalNameToLCID")) + { + primary = PRIMARYLANGID(lcid); + sublang = SUBLANGID(lcid); + swprintf_s(message, L"LocaleNameToLCID succeeded: %u\n\tPrimary ID: %u\n\tSublanguage: %u\n", lcid, primary, sublang); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("LocaleNameToLCID failed!"); + } + + // The GetUserGeoID() API can be used to get the actual country the kit is in. + // It gives you the country selected through the Settings app + long geoID = GetUserGeoID(GEOCLASS_NATION); + wchar_t geoData[LOCALE_NAME_MAX_LENGTH]; + retVal = GetGeoInfoW(geoID, GEO_LATITUDE, geoData, ARRAYSIZE(geoData), primary); + if (FunctionSucceeded(retVal, L"GetGeoInfoW")) + { + swprintf_s(message, L"Lattitude query succeeded: %s\n", geoData); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("GetGeoInfoW failed in GEO_LATTITUDE!"); + } + + retVal = GetGeoInfoW(geoID, GEO_LONGITUDE, geoData, ARRAYSIZE(geoData), primary); + if (FunctionSucceeded(retVal, L"GetGeoInfoW")) + { + swprintf_s(message, L"Longitude query succeeded: %s\n", geoData); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("GetGeoInfoW failed on GEO_LONGITUDE!"); + } + + retVal = GetGeoInfoW(geoID, GEO_NATION, geoData, ARRAYSIZE(geoData), primary); + if (FunctionSucceeded(retVal, L"GetGeoInfoW")) + { + swprintf_s(message, L"Nation query succeeded: %s\n", geoData); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("GetGeoInfoW failed on GEO_NATION!"); + } + + wchar_t iso2[3]; + retVal = GetGeoInfoW(geoID, GEO_ISO2, iso2, ARRAYSIZE(iso2), primary); + if (FunctionSucceeded(retVal, L"GetGeoInfoW")) + { + swprintf_s(message, L"Iso2 query succeeded: %s\n", iso2); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("GetGeoInfoW failed on GEO_ISO2!"); + } + + wchar_t iso3[4]; + retVal = GetGeoInfoW(geoID, GEO_ISO3, iso3, ARRAYSIZE(iso3), primary); + if (FunctionSucceeded(retVal, L"GetGeoInfoW")) + { + swprintf_s(message, L"Iso3 query succeeded: %s\n", iso3); + OutputDebugString(message); + m_textConsole->Write(message); + } + else + { + throw std::exception("GetGeoInfoW failed on GEO_ISO3!"); + } + + // The country values returned from GetUserDefaultLocaleName() and GetUserGeoID() can be compared + // to determine if the country selected by the user is supported by the app or not + std::wstring localeNameStr(userLocaleName); + std::wstring::size_type pos = localeNameStr.find(L'-'); + localeNameStr = localeNameStr.substr(pos + 1); + if (_wcsicmp(localeNameStr.c_str(), iso2) == 0 || _wcsicmp(localeNameStr.c_str(), iso3) == 0) + { + m_textConsole->Format(L"Selected locale in manifest. Country: %s\n", iso2); + } + else + { + m_textConsole->Format(L"The selected locale (Country: %s) is NOT present in the manifest, so the fallback locale (Country: %s) is selected for localization\n", iso2, localeNameStr.c_str()); + } + + wchar_t lcpData[LOCALE_NAME_MAX_LENGTH]; + retVal = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO639LANGNAME, lcpData, ARRAYSIZE(lcpData)); + if (FunctionSucceeded(retVal, L"GetLocaleInfoEx")) + { + m_textConsole->Format(L"GetLocaleInfoEx() - LOCALE_SISO639LANGNAME: %s\n", lcpData); + } + else + { + throw std::exception("GetLocaleInfoEx failed on LOCALE_SISO639LANGNAME!"); + } + + retVal = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE, lcpData, ARRAYSIZE(lcpData)); + if (FunctionSucceeded(retVal, L"GetLocaleInfoEx")) + { + m_textConsole->Format(L"GetLocaleInfoEx() - LOCALE_IDEFAULTLANGUAGE: %s\n", lcpData); + } + else + { + throw std::exception("GetLocaleInfoEx failed on LOCALE_IDEFAULTLANGUAGE!"); + } +} + +bool Sample::FunctionSucceeded(int returned, const wchar_t* function) +{ + if (returned == 0) + { + unsigned long error = GetLastError(); + wchar_t message[1024] = { L'\0' }; + swprintf_s(message, L"%s failed with error: %u\n", function, error); + OutputDebugString(message); + return false; + } + return true; +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + m_textConsole->Render(); + + m_sprites->Begin(); + m_sprites->Draw(m_texture.Get(), XMFLOAT2(800, 75), nullptr, Colors::White, 0.f, XMFLOAT2(0, 0), 0.2f); + m_sprites->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + // setup the text console for output + m_textConsole->RestoreDevice(context, L"SegoeUI_18.spritefont"); + + // parse the resource file to find the right localized image to display + ResourceParser resParser(m_localeName, m_imagePrepend); + DX::ThrowIfFailed(resParser.ParseFile(m_resFileName)); + Platform::String^ idImage = ref new Platform::String(L"Gamepad"); + Platform::String^ imageString = resParser.GetImage(idImage); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, imageString->Data(), nullptr, m_texture.ReleaseAndGetAddressOf())); + + m_sprites = std::make_unique(context); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto rect = m_deviceResources->GetOutputSize(); + m_textConsole->SetWindow(rect); +} +#pragma endregion diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.h b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.h new file mode 100644 index 0000000000000000000000000000000000000000..954672f887b0b676fab27e5b36f861f26c03fb65 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// NLSAndLocalization.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void InitializeLocalization(); + + bool FunctionSucceeded(int returned, const wchar_t* function); + + std::unique_ptr m_textConsole; + Microsoft::WRL::ComPtr m_texture; + std::unique_ptr m_sprites; + + wchar_t m_imagePrepend[256]; + wchar_t m_resFileName[256]; + wchar_t m_localeName[LOCALE_NAME_MAX_LENGTH]; + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; +}; diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.vcxproj b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..f7b6808b8e761d0412746d8093aded6cc993f40f --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.vcxproj @@ -0,0 +1,268 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + NLSAndLocalization + {53cc0a60-33e5-4059-9db1-647b9a94c2c4} + en-US + Win32Proj + title + + v140 + 14.0 + Native + Never + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + + + + + Document + + + true + Document + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.vcxproj.filters b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..2d8751505321137c7bd466c9afea4f656a381428 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/NLSAndLocalization.vcxproj.filters @@ -0,0 +1,157 @@ + + + + + d87847c6-6240-49a1-86ae-47d8037b38d9 + + + bd924ec7-35b4-42b8-8c41-60d8451d951e + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {3af23210-1c28-4e4f-a47e-fccc6eb70ec7} + + + {ef6eeb33-e16b-489f-b797-345ae1d76a2b} + + + {86c12911-4283-4a85-89e0-80d90b06083d} + + + {caab2900-4a17-4593-bfc3-5c77e8552698} + + + {f40cc47a-1daa-42a5-a13b-744963f80ff6} + + + {fa0c3186-2fa1-4c08-bc94-dfdfd21c102b} + + + {5ba16bc1-9055-491b-ac39-a430f827ec66} + + + {aec18534-afcc-46dc-be47-1ecfb1a976b1} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + de-DE + + + en + + + en-GB + + + en-US + + + fr + + + fr-FR + + + ja-JP + + + + + de-DE + + + en + + + en-GB + + + en-US + + + fr + + + fr-FR + + + ja-JP + + + + + + + de-DE + + + en + + + en-GB + + + en-US + + + fr + + + fr-FR + + + ja-JP + + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Package.appxmanifest b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..578104bc64f2ffe98db4deefef533ad6abb06e25 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Package.appxmanifest @@ -0,0 +1,65 @@ + + + + + + + NLSAndLocalization + Xbox Advanced Technology Group + Assets\StoreLogo.png + NLSAndLocalization + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Readme.docx b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..9f0d133dcd3d4df25283ae09f514a7a6d47c5740 Binary files /dev/null and b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Readme.docx differ diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ResourceParser.cpp b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ResourceParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c12874b2b535951673747eda21e66b03dfc1fc7 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ResourceParser.cpp @@ -0,0 +1,205 @@ +//-------------------------------------------------------------------------------------- +// ResourceParser.cpp +// +// Class to handle resource parsing. +// +// This is just a sample class parsing some temporary resource files. +// The resource files can be in any format you choose. +// This class doesn't perform many checks against wrong file formatting. +// It assumes that the resource file will not be tampered with. The goal is to show +// how to use resources for localization. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once +#include "pch.h" +#include "ResourceParser.h" + +#define FILE_CONTENT_SIZE 2048 + +ResourceParser::ResourceParser(void) +{ + m_localeName = ref new Platform::String(); + m_appendImageStr = ref new Platform::String(); + m_stringMap = ref new Platform::Collections::Map< Platform::String^, Platform::String^ >( ); + m_imageMap = ref new Platform::Collections::Map< Platform::String^, Platform::String^ >( ); +} + +ResourceParser::ResourceParser( wchar_t* localeName, wchar_t* appendImageStr ) +{ + m_localeName = ref new Platform::String( localeName ); + m_appendImageStr = ref new Platform::String( appendImageStr ); + m_stringMap = ref new Platform::Collections::Map< Platform::String^, Platform::String^ >( ); + m_imageMap = ref new Platform::Collections::Map< Platform::String^, Platform::String^ >( ); +} + +// Parse the resources file to get the string and image data +HRESULT ResourceParser::ParseFile( const wchar_t* fileName ) +{ + HANDLE hFile = CreateFile2( fileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + NULL ); + + if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) + { + return GetLastError(); + } + + // Read the file contents into a buffer + wchar_t buf[ FILE_CONTENT_SIZE ]; + DWORD charRead; + if ( hFile ) + { + DWORD bytesRead; + if ( !ReadFile( hFile, buf, FILE_CONTENT_SIZE, &bytesRead, NULL ) ) + { + return GetLastError(); + } + + charRead = bytesRead / sizeof( wchar_t ); + buf[charRead] = '\0'; + } + + std::wstring wstrbuf( buf ); + while ( wstrbuf.length() > 0 ) + { + std::wstring wstr; + + std::string token; + std::wstring::size_type pos1, pos2, bufEndPos; + Platform::String^ idToken = ref new Platform::String( L"" ); + Platform::String^ valueToken = ref new Platform::String( L"" ); + + pos1 = wstrbuf.find( L'<' ); + pos2 = wstrbuf.find( L'>' ); + bufEndPos = pos2; + + // Handle the case where a / is present just before /> + if( wstrbuf[ pos2-1 ] == '/' ) + { + --pos2; + } + wstr = wstrbuf.substr( pos1+1, pos2-(pos1+1) ); + wstrbuf = wstrbuf.substr( bufEndPos+1 ); + + TrimString( wstr ); + pos1 = wstr.find(L' '); + std::wstring resType = wstr.substr( 0, pos1 ); + wstr = wstr.substr( pos1+1 ); + + // Parse the data within a node into Id and Value attributes + // The assumption is that all the nodes in the resource file will have an Id and Value field + // Put these values into a map which can be retrieved later from the app as and when required + // Create a separate map for image and string data + while( wstr.length() > 0 ) + { + pos1 = wstr.find(L'='); + std::wstring token1 = wstr.substr( 0, pos1 ); + TrimString( token1 ); + wstr = wstr.substr( pos1+1 ); + + // Find the string between quotes + pos1 = wstr.find( '"' ); + if ( pos1 == std::wstring::npos ) + { + // Error in structure + return S_FALSE; + } + pos2 = wstr.find( '"', pos1+1 ); + + while ( pos2 != std::wstring::npos && wstr[pos2-1] == '\\' ) + { + // Check if a backslash is present within the string. Ignore those quotes + pos2 = wstr.find( '"', pos2+1 ); + } + if ( pos2 == std::wstring::npos ) + { + // Error in structure + return S_FALSE; + } + + std::wstring token2 = wstr.substr( pos1+1, pos2-(pos1+1) ); + TrimString( token2 ); + wstr = wstr.substr( pos2+1 ); + + if ( _wcsicmp( token1.c_str(), L"ID" ) == 0 ) + { + idToken = nullptr; + idToken = ref new Platform::String( token2.c_str() ); + } + else if ( _wcsicmp( token1.c_str(), L"Value" ) == 0 ) + { + valueToken = nullptr; + valueToken = ref new Platform::String( token2.c_str() ); + } + + if ( idToken->Length() > 0 && valueToken->Length() > 0 ) + { + if ( _wcsicmp( resType.c_str(), L"String" ) == 0 ) + { + m_stringMap->Insert( idToken, valueToken ); + } + else if ( _wcsicmp( resType.c_str(), L"Image" ) == 0 ) + { + valueToken = valueToken->Concat( m_appendImageStr, valueToken ); + m_imageMap->Insert( idToken, valueToken ); + } + idToken = nullptr; + valueToken = nullptr; + } + + } + } + + CloseHandle( hFile ); + return S_OK; +} + +// Trim the string to remove spaces from its beginning and end +void ResourceParser::TrimString( std::wstring& wstr ) +{ + // Remove spaces from the begining + UINT spaceCnt = ( UINT ) wstr.find_first_not_of( L' ' ); + wstr = wstr.substr( spaceCnt ); + + // Remove spaces from the end + spaceCnt = ( UINT ) wstr.find_last_not_of( L' ' ); + wstr = wstr.substr( 0, spaceCnt + 1 ); +} + +// Get the string value based on the Id +Platform::String^ ResourceParser::GetString( Platform::String^ id ) +{ + if ( m_stringMap->HasKey( id ) ) + { + return m_stringMap->Lookup( id ); + } + else + { + return nullptr; + } +} + +// Get the image name based on the Id +Platform::String^ ResourceParser::GetImage( Platform::String^ id ) +{ + if ( m_imageMap->HasKey( id ) ) + { + return m_imageMap->Lookup( id ); + } + else + { + return nullptr; + } +} + +ResourceParser::~ResourceParser(void) +{ + m_localeName = nullptr; + m_stringMap = nullptr; + m_imageMap = nullptr; +} diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ResourceParser.h b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ResourceParser.h new file mode 100644 index 0000000000000000000000000000000000000000..e781f8727d871ec76391af80f276a7ce45757564 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ResourceParser.h @@ -0,0 +1,38 @@ +//-------------------------------------------------------------------------------------- +// ResourceParser.h +// +// Class to handle resource parsing. +// +// This is just a sample class parsing some temporary resource files. +// The resource files can be in any format you choose. +// This class doesn't perform many checks against wrong file formatting. +// It assumes that the resource file will not be tampered with. The goal is to show +// how to use resources for localization. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once +#include "pch.h" +#include + +class ResourceParser +{ +public: + ResourceParser(void); + ResourceParser( wchar_t* localeName, wchar_t* appendImageStr ); + ~ResourceParser(void); + + HRESULT ParseFile( const wchar_t* filename ); + Platform::String^ GetString( Platform::String^ id ); + Platform::String^ GetImage( Platform::String^ id ); + +private: + void TrimString( std::wstring& wstr ); + + Platform::String^ m_localeName; + Platform::String^ m_appendImageStr; + Platform::Collections::Map< Platform::String^, Platform::String^ >^ m_stringMap; + Platform::Collections::Map< Platform::String^, Platform::String^ >^ m_imageMap; +}; diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/StepTimer.h b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Telemetry.h b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/de-DE/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/de-DE/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..9608eaf1da518f4c79ad89826cd4467dcc3d973a --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/de-DE/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (de-DE) + App Description + + + NLS And Localization (de-DE) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en-GB/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en-GB/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..1dcc48f920be68bf8ba5a2684ee3d4892a94c953 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en-GB/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (en-GB) + App Description + + + NLS And Localization (en-GB) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en-US/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en-US/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..e9d6b57c0df53ec50f29faecb49147aff53626d2 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en-US/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (en-US) + App Description + + + NLS And Localization (en-US) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..a02969a4adc235af121a191700a66122ecc2016b --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/en/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (en) + App Description + + + NLS And Localization (en) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/fr-FR/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/fr-FR/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..f00d1a2ccb4fbcaf9722b5c8733c11b0d0ed4e89 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/fr-FR/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (fr-FR) + App Description + + + NLS And Localization (fr-FR) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/fr/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/fr/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..1013d0ae48bac4c9eaebf25a8b9c70de26adb782 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/fr/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (fr) + App Description + + + NLS And Localization (fr) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ja-JP/Resources.resw b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ja-JP/Resources.resw new file mode 100644 index 0000000000000000000000000000000000000000..8e74fcad3bf8a0df53b582864134b0365f1f44d9 --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/ja-JP/Resources.resw @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sample for NLS APIs and localization (ja-JP) + App Description + + + NLS And Localization (ja-JP) + Name of the App + + \ No newline at end of file diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/pch.cpp b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/pch.h b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..db657bd800bc6e6257f940e992e1456181d6ccdc --- /dev/null +++ b/XDKSamples/System/NLSAndLocalization/NLSAndLocalization/pch.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +#include "TextConsole.h" +#include "ATGColors.h" +#include "DDSTextureLoader.h" +#include "ResourceParser.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/SimpleFrontPanel/Assets/Logo.png b/XDKSamples/System/SimpleFrontPanel/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c0fc7df8cd1c677853b40c147a5a57a0e733cea6 Binary files /dev/null and b/XDKSamples/System/SimpleFrontPanel/Assets/Logo.png differ diff --git a/XDKSamples/System/SimpleFrontPanel/Assets/SmallLogo.png b/XDKSamples/System/SimpleFrontPanel/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c352cc68fce5c0410210abbe08188ef1159ec0d2 Binary files /dev/null and b/XDKSamples/System/SimpleFrontPanel/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/SimpleFrontPanel/Assets/SplashScreen.png b/XDKSamples/System/SimpleFrontPanel/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..96fede95bd502a1bb17ca64976c397455711f69a Binary files /dev/null and b/XDKSamples/System/SimpleFrontPanel/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/SimpleFrontPanel/Assets/StoreLogo.png b/XDKSamples/System/SimpleFrontPanel/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/SimpleFrontPanel/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/SimpleFrontPanel/Assets/WideLogo.png b/XDKSamples/System/SimpleFrontPanel/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..02ba097439184f85fe04530259c8dab9dc303988 Binary files /dev/null and b/XDKSamples/System/SimpleFrontPanel/Assets/WideLogo.png differ diff --git a/XDKSamples/System/SimpleFrontPanel/DeviceResources.cpp b/XDKSamples/System/SimpleFrontPanel/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29759abd16cd8674d19a6bdb3f66507f0e0990ea --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/DeviceResources.cpp @@ -0,0 +1,325 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat((flags & c_EnableHDR) ? DXGI_FORMAT_R10G10B10A2_UNORM : backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags), + m_gameDVRFormat((flags & c_EnableHDR) ? backBufferFormat : DXGI_FORMAT_UNKNOWN) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + if (m_options & c_Enable4K_UHD) + { +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + m_d3dDevice->GetGpuHardwareConfiguration(&hwConfig); + if (hwConfig.HardwareVersion >= D3D11X_HARDWARE_VERSION_XBOX_ONE_X) + { + m_outputSize = { 0, 0, 3840, 2160 }; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 4k (3840 x 2160) on Xbox One X\n"); +#endif + } + else + { + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("INFO: Swapchain using 1080p (1920 x 1080) on Xbox One or Xbox One S\n"); +#endif + } +#else + m_options &= ~c_Enable4K_UHD; +#ifdef _DEBUG + OutputDebugStringA("WARNING: Hardware detection not supported on this XDK edition; Swapchain using 1080p (1920 x 1080)\n"); +#endif +#endif + } +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr, nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dGameDVRRenderTargetView.Reset(); + m_d3dGameDVRRenderTarget.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_gameDVRFormat, + 0 + )); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = (m_options & c_EnableHDR) ? DXGIX_SWAP_CHAIN_FLAG_COLORIMETRY_RGB_BT2020_ST2084 : DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + + if ((m_options & c_EnableHDR) && !m_swapChainGameDVR) + { + swapChainDesc.Format = m_gameDVRFormat; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChainGameDVR.GetAddressOf() + )); + } + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_renderTarget->SetName(L"Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dGameDVRRenderTarget->SetName(L"GameDVR Render target"); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_d3dGameDVRRenderTarget.Get(), + nullptr, + m_d3dGameDVRRenderTargetView.ReleaseAndGetAddressOf() + )); + } + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + + if (m_swapChainGameDVR) + { + ThrowIfFailed(m_swapChainGameDVR->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_d3dGameDVRRenderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_d3dGameDVRRenderTarget.Get(), m_d3dGameDVRRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_d3dGameDVRRenderTarget.Get()); + } + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + + if (m_d3dGameDVRRenderTarget) + { + m_d3dContext->DecompressResource( + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_d3dGameDVRRenderTarget.Get(), 0, nullptr, + m_gameDVRFormat, decompressFlags); + } + } + + if (m_swapChainGameDVR) + { + IDXGISwapChain1* ppSwapChains[2] = { m_swapChain.Get(), m_swapChainGameDVR.Get() }; + + DXGIX_PRESENTARRAY_PARAMETERS presentParameterSets[2] = {}; + presentParameterSets[0].SourceRect = m_outputSize; + presentParameterSets[0].ScaleFactorHorz = 1.0f; + presentParameterSets[0].ScaleFactorVert = 1.0f; + + presentParameterSets[1].SourceRect = m_outputSize; + presentParameterSets[1].ScaleFactorHorz = 1.0f; + presentParameterSets[1].ScaleFactorVert = 1.0f; + + DXGIXPresentArray(1, 0, 0, _countof(presentParameterSets), ppSwapChains, presentParameterSets); + } + else + { + ThrowIfFailed(m_swapChain->Present(1, 0)); + } + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/SimpleFrontPanel/DeviceResources.h b/XDKSamples/System/SimpleFrontPanel/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..1edd14523e9006c77bca692edc98d8732d1b0e67 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/DeviceResources.h @@ -0,0 +1,84 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + static const unsigned int c_Enable4K_UHD = 0x2; + static const unsigned int c_EnableHDR = 0x4; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + // Direct3D HDR Game DVR support for Xbox One. + IDXGISwapChain1* GetGameDVRSwapChain() const { return m_swapChainGameDVR.Get(); } + ID3D11Texture2D* GetGameDVRRenderTarget() const { return m_d3dGameDVRRenderTarget.Get(); } + ID3D11RenderTargetView* GetGameDVRRenderTargetView() const { return m_d3dGameDVRRenderTargetView.Get(); } + DXGI_FORMAT GetGameDVRFormat() const { return m_gameDVRFormat; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + + // Direct3D HDR Game DVR support for Xbox One. + Microsoft::WRL::ComPtr m_swapChainGameDVR; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTarget; + Microsoft::WRL::ComPtr m_d3dGameDVRRenderTargetView; + DXGI_FORMAT m_gameDVRFormat; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/SimpleFrontPanel/Main.cpp b/XDKSamples/System/SimpleFrontPanel/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3304857cb8e7b3b0cf363c3004fa7cc86eeafb34 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/Main.cpp @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleFrontPanel.h" + +#include "Telemetry.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Sample Usage Telemetry + // + // Disable or remove this code block to opt-out of sample usage telemetry + // + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + auto deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ /*argv*/) +{ + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} + + +// Exit helper +void ExitSample() +{ + Windows::ApplicationModel::Core::CoreApplication::Exit(); +} \ No newline at end of file diff --git a/XDKSamples/System/SimpleFrontPanel/Package.appxmanifest b/XDKSamples/System/SimpleFrontPanel/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..ca5f39c8a67dcd3d457f578db95b15011cdc5f49 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SimpleFrontPanel + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimpleFrontPanel + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/SimpleFrontPanel/Readme.docx b/XDKSamples/System/SimpleFrontPanel/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..abce1121442e19c2213eeaec4e90461b46464b69 Binary files /dev/null and b/XDKSamples/System/SimpleFrontPanel/Readme.docx differ diff --git a/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.cpp b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb4c1b50411fd4b203fa071f953899ccfbd24bf4 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.cpp @@ -0,0 +1,445 @@ +//-------------------------------------------------------------------------------------- +// SimpleFrontPanel.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleFrontPanel.h" + +#include "ATGColors.h" + +#include "FileHelpers.h" +#include "OSHelpers.h" + +namespace +{ + // For more information, see DirectX Tool Kit's dds.h + const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#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_PITCH 0x00000008 // DDSD_PITCH +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE + +#pragma pack(push, 1) + struct DDS_PIXELFORMAT + { + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; + }; + + struct DDS_HEADER + { + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; + }; +#pragma pack(pop) + + const DDS_PIXELFORMAT DDSPF_L8 = { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; +} + +extern void ExitSample(); + +using namespace ATG; +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() + : m_frame(0) + , m_screenWidth(0) + , m_screenHeight(0) + , m_rememberedButtons(XBOX_FRONT_PANEL_BUTTONS_NONE) + , m_dirty(false) + , m_checkerboard(false) +{ + // Renders only 2D, so no need for a depth buffer. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + if (IsXboxFrontPanelAvailable()) + { + // Get the default front panel + DX::ThrowIfFailed(GetDefaultXboxFrontPanel(m_frontPanelControl.ReleaseAndGetAddressOf())); + + // Get the screen width and height and allocate a panel buffer + DX::ThrowIfFailed(m_frontPanelControl->GetScreenWidth(&m_screenWidth)); + DX::ThrowIfFailed(m_frontPanelControl->GetScreenHeight(&m_screenHeight)); + m_panelBuffer = std::unique_ptr(new uint8_t[m_screenWidth * m_screenHeight]); + + // Fill the panel buffer with a checkerboard pattern + CheckerboardFillPanelBuffer(); + + XBOX_FRONT_PANEL_LIGHTS lights = XBOX_FRONT_PANEL_LIGHTS_NONE; + DX::ThrowIfFailed(m_frontPanelControl->SetLightStates(lights)); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + ExitSample(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + if(m_frontPanelControl) + { + XBOX_FRONT_PANEL_BUTTONS previousButtons = m_rememberedButtons; + DX::ThrowIfFailed(m_frontPanelControl->GetButtonStates(&m_rememberedButtons)); + XBOX_FRONT_PANEL_BUTTONS pressedButtons = XBOX_FRONT_PANEL_BUTTONS((previousButtons ^ m_rememberedButtons) & m_rememberedButtons); + + // Use DPAD left and right to toggle between checkerboard and gradient + if ((pressedButtons & XBOX_FRONT_PANEL_BUTTONS_LEFT) || (pressedButtons & XBOX_FRONT_PANEL_BUTTONS_RIGHT)) + { + m_checkerboard = !m_checkerboard; + if (m_checkerboard) + { + CheckerboardFillPanelBuffer(); + } + else + { + GradientFillPanelBuffer(); + } + } + + if (pressedButtons & XBOX_FRONT_PANEL_BUTTONS_UP) + { + BrightenPanelBuffer(); + } + + if (pressedButtons & XBOX_FRONT_PANEL_BUTTONS_DOWN) + { + DimPanelBuffer(); + } + + unsigned whichButton = XBOX_FRONT_PANEL_BUTTONS_BUTTON1; + + for (; whichButton <= XBOX_FRONT_PANEL_BUTTONS_BUTTON5; whichButton = whichButton << 1) + { + if (pressedButtons & whichButton) + { + ToggleButtonLight(XBOX_FRONT_PANEL_BUTTONS(whichButton)); + } + } + + if (pressedButtons & XBOX_FRONT_PANEL_BUTTONS_SELECT) + { + CaptureFrontPanelScreen(L"D:\\FrontPanelScreen.dds"); +#ifdef _DEBUG + OutputDebugStringA("Screenshot of front panel display written to development drive.\n"); +#endif + } + + PresentFrontPanel(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto output = m_deviceResources->GetOutputSize(); + + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(output.right, output.bottom); + + m_batch->Begin(); + m_batch->Draw(m_background.Get(), output); + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + m_batch = std::make_unique(context); + + DX::ThrowIfFailed( + CreateWICTextureFromFile(device, + IsXboxFrontPanelAvailable() ? L"FrontPanelPresent.png" : L"NoFrontPanel.png", + nullptr, m_background.ReleaseAndGetAddressOf()) + ); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion + +void Sample::CheckerboardFillPanelBuffer() +{ + uint8_t *data = m_panelBuffer.get(); + for (unsigned i = 0; i < m_screenWidth; ++i) + { + for (unsigned j = 0; j < m_screenHeight; ++j) + { + uint8_t color = ((i / 16 & 1) ^ (j / 16 & 1)) * 0xFF; + data[i + j * m_screenWidth] = color; + } + } + m_dirty = true; + m_checkerboard = true; +} + +void Sample::GradientFillPanelBuffer() +{ + uint8_t *data = m_panelBuffer.get(); + uint8_t colorBand = uint8_t(m_screenWidth / 16); + for (unsigned i = 0; i < m_screenWidth; ++i) + { + for (unsigned j = 0; j < m_screenHeight; ++j) + { + uint8_t color = uint8_t((i / colorBand) << 4); + data[i + j * m_screenWidth] = color; + } + } + m_dirty = true; + m_checkerboard = false; +} + +void Sample::DimPanelBuffer() +{ + uint8_t *data = m_panelBuffer.get(); + for (unsigned i = 0; i < m_screenWidth; ++i) + { + for (unsigned j = 0; j < m_screenHeight; ++j) + { + uint8_t color = data[i + j * m_screenWidth]; + if (color >= 0x10) + { + color -= 0x10; + data[i + j * m_screenWidth] = color; + } + } + } + m_dirty = true; +} + +void Sample::BrightenPanelBuffer() +{ + uint8_t *data = m_panelBuffer.get(); + for (unsigned i = 0; i < m_screenWidth; ++i) + { + for (unsigned j = 0; j < m_screenHeight; ++j) + { + uint8_t color = data[i + j * m_screenWidth]; + if (color < 0xF0) + { + color += 0x10; + data[i + j * m_screenWidth] = color; + } + } + } + m_dirty = true; +} + +void Sample::ToggleButtonLight(XBOX_FRONT_PANEL_BUTTONS whichButton) +{ + XBOX_FRONT_PANEL_LIGHTS lights = XBOX_FRONT_PANEL_LIGHTS_NONE; + DX::ThrowIfFailed(m_frontPanelControl->GetLightStates(&lights)); + lights = XBOX_FRONT_PANEL_LIGHTS(lights ^ (XBOX_FRONT_PANEL_LIGHTS(whichButton))); + DX::ThrowIfFailed(m_frontPanelControl->SetLightStates(lights)); +} + +void Sample::PresentFrontPanel() +{ + // It is only necessary to present to the front panel when pixels have changed. + if (m_dirty) + { + DX::ThrowIfFailed(m_frontPanelControl->PresentBuffer(m_screenWidth * m_screenHeight, m_panelBuffer.get())); + m_dirty = false; + } +} + +void Sample::CaptureFrontPanelScreen(const wchar_t * fileName) +{ + if (!fileName) + { + throw std::invalid_argument("Invalid filename"); + } + + // Create file + ScopedHandle hFile(safe_handle(CreateFile2(fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr))); + + if (!hFile) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + auto_delete_file delonfail(hFile.get()); + + // Setup header + const size_t HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER); + uint8_t fileHeader[HEADER_SIZE] = {}; + + *reinterpret_cast(&fileHeader[0]) = DDS_MAGIC; + + auto header = reinterpret_cast(&fileHeader[0] + sizeof(uint32_t)); + header->size = sizeof(DDS_HEADER); + header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; + header->height = m_screenHeight; + header->width = m_screenWidth; + header->mipMapCount = 1; + header->caps = DDS_SURFACE_FLAGS_TEXTURE; + memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_L8, sizeof(DDS_PIXELFORMAT)); + + UINT rowPitch = m_screenWidth; + UINT slicePitch = m_screenWidth * m_screenHeight; + + header->flags |= DDS_HEADER_FLAGS_PITCH; + header->pitchOrLinearSize = static_cast(rowPitch); + + // Write header & pixels + DWORD bytesWritten = 0; + if (!WriteFile(hFile.get(), fileHeader, static_cast(HEADER_SIZE), &bytesWritten, nullptr)) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + if (bytesWritten != HEADER_SIZE) + { + throw std::exception("WriteFile"); + } + + if (!WriteFile(hFile.get(), m_panelBuffer.get(), static_cast(slicePitch), &bytesWritten, nullptr)) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + if (bytesWritten != slicePitch) + { + throw std::exception("WriteFile"); + } + + delonfail.clear(); +} diff --git a/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.h b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.h new file mode 100644 index 0000000000000000000000000000000000000000..6f01e518b476de4de8d5567181e4f93eea20e20a --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.h @@ -0,0 +1,97 @@ +//-------------------------------------------------------------------------------------- +// SimpleFrontPanel.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Fill the front panel buffer with a checkerboard pattern + void CheckerboardFillPanelBuffer(); + + // Fill the front panel buffer with a gradient pattern + void GradientFillPanelBuffer(); + + // Reduce the brightness of the panel buffer pixels + void DimPanelBuffer(); + + // Increase the brightness of the panel buffer pixels + void BrightenPanelBuffer(); + + // Toggle the light associated with the provided button + void ToggleButtonLight(XBOX_FRONT_PANEL_BUTTONS whichButton); + + // Conditionally present the front panel when there are dirty pixels + void PresentFrontPanel(); + + // Save the contents of the front panel buffer as a .dds surface + void CaptureFrontPanelScreen(const wchar_t *fileName); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_batch; + Microsoft::WRL::ComPtr m_background; + + // XboxFrontPanel objects + Microsoft::WRL::ComPtr m_frontPanelControl; + + uint32_t m_screenWidth; + uint32_t m_screenHeight; + + // Tracks the buttons states from the previous update in order to facilitate "button held" events + XBOX_FRONT_PANEL_BUTTONS m_rememberedButtons; + std::unique_ptr m_panelBuffer; + + // The m_dirty member will be set whenever there are changes to front panel pixels. + // This way we will only call IXboxFrontPanelControl::PresentBuffer() when there + // are changes to pixels. Note that it is only necessary to present to the front + // panel when there are changes to the pixels. + bool m_dirty; + bool m_checkerboard; +}; diff --git a/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.sln b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.sln new file mode 100644 index 0000000000000000000000000000000000000000..cbfd3c9a3af0be44272b33f7f42914588d7dc76c --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleFrontPanel", "SimpleFrontPanel.vcxproj", "{3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Debug|Durango.ActiveCfg = Debug|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Debug|Durango.Build.0 = Debug|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Debug|Durango.Deploy.0 = Debug|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Profile|Durango.ActiveCfg = Profile|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Profile|Durango.Build.0 = Profile|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Profile|Durango.Deploy.0 = Profile|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Release|Durango.ActiveCfg = Release|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Release|Durango.Build.0 = Release|Durango + {3EF23CD9-F059-4FD0-A41A-D7637D18C6F4}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.vcxproj b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..39b4c9eca57cb65f457eab4a430b8f7c67b15210 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.vcxproj @@ -0,0 +1,212 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimpleFrontPanel + {3ef23cd9-f059-4fd0-a41a-d7637d18c6f4} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + xboxfrontpanel.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + xboxfrontpanel.lib;pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.vcxproj.filters b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..1eca93af4174e128fb68b3d0317b5cd9f10f6e02 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/SimpleFrontPanel.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + 9e6c8144-44e4-4f2d-bf4e-72571eb59353 + + + 4b13f9bb-9a10-42bc-b19c-3e560ae39479 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {40bad68e-e902-4859-a8c4-17e1144c9c78} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/SimpleFrontPanel/StepTimer.h b/XDKSamples/System/SimpleFrontPanel/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/SimpleFrontPanel/Telemetry.h b/XDKSamples/System/SimpleFrontPanel/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/SimpleFrontPanel/pch.cpp b/XDKSamples/System/SimpleFrontPanel/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/SimpleFrontPanel/pch.h b/XDKSamples/System/SimpleFrontPanel/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..62a086202e4d3fe0b7257fedf95fb484a9bfbfba --- /dev/null +++ b/XDKSamples/System/SimpleFrontPanel/pch.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x3AD703ED /* XDK Edition 170300 */ +#error This sample requires the March 2017 XDK or later +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "WICTextureLoader.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/SimplePLM/Readme.docx b/XDKSamples/System/SimplePLM/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..f1c1a2434a3768589acd14ff955991c6b6a445bd Binary files /dev/null and b/XDKSamples/System/SimplePLM/Readme.docx differ diff --git a/XDKSamples/System/SimplePLM/SimplePLM.sln b/XDKSamples/System/SimplePLM/SimplePLM.sln new file mode 100644 index 0000000000000000000000000000000000000000..a7d1f9d8ba7ee2a3310588b80f4166b6d50a3c0e --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimplePLM", "SimplePLM\SimplePLM.vcxproj", "{57402841-95AD-4A7C-8821-F01F8356CCC7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Debug|Durango.ActiveCfg = Debug|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Debug|Durango.Build.0 = Debug|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Debug|Durango.Deploy.0 = Debug|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Profile|Durango.ActiveCfg = Profile|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Profile|Durango.Build.0 = Profile|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Profile|Durango.Deploy.0 = Profile|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Release|Durango.ActiveCfg = Release|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Release|Durango.Build.0 = Release|Durango + {57402841-95AD-4A7C-8821-F01F8356CCC7}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Assets/Logo.png b/XDKSamples/System/SimplePLM/SimplePLM/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/SimplePLM/SimplePLM/Assets/Logo.png differ diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Assets/SmallLogo.png b/XDKSamples/System/SimplePLM/SimplePLM/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/SimplePLM/SimplePLM/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Assets/SplashScreen.png b/XDKSamples/System/SimplePLM/SimplePLM/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/SimplePLM/SimplePLM/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Assets/StoreLogo.png b/XDKSamples/System/SimplePLM/SimplePLM/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/SimplePLM/SimplePLM/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Assets/WideLogo.png b/XDKSamples/System/SimplePLM/SimplePLM/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/SimplePLM/SimplePLM/Assets/WideLogo.png differ diff --git a/XDKSamples/System/SimplePLM/SimplePLM/DeviceResources.cpp b/XDKSamples/System/SimplePLM/SimplePLM/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/SimplePLM/SimplePLM/DeviceResources.h b/XDKSamples/System/SimplePLM/SimplePLM/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Main.cpp b/XDKSamples/System/SimplePLM/SimplePLM/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f073929de65f0681794bc7c23ae7957cdc984628 --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/Main.cpp @@ -0,0 +1,220 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimplePLM.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + CoreApplication::ResourceAvailabilityChanged += + ref new EventHandler(this, &ViewProvider::OnResourceAvailabilityChanged); + + m_sample = std::make_unique(); + m_sample->ShowInstructions(); + m_sample->LogPLMEvent(L"Initialize()"); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnWindowActivated); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + m_sample->LogPLMEvent(L"SetWindow()"); + } + + virtual void Load(Platform::String^ entryPoint) + { + m_sample->LogPLMEvent(L"Load()", entryPoint->Data()); + } + + virtual void Run() + { + m_sample->LogPLMEvent(L"Run()"); + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + Platform::String^ argsData = args->Kind.ToString() + " : " + launchArgs->Arguments; + m_sample->LogPLMEvent(L"OnActivated()", argsData->Data()); + } + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + + if (m_sample->GetUseDeferral()) + { + //GetDeferral must be called on the Core Window thread. The deferral can then be passed to other threads. + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + //The deferral can be used to complete suspending on other threads after the OnSuspending handler has returned. + concurrency::create_task([this, deferral]() + { + m_sample->LogPLMEvent(L"OnSuspending()", L"using a deferral"); + m_sample->OnSuspending(); + deferral->Complete(); + }); + } + else + { + //Without a deferral, the application will complete suspending as soon as it returns from the OnSuspending handler. + m_sample->LogPLMEvent(L"OnSuspending()", L"not using a deferral"); + m_sample->OnSuspending(); + } + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->LogPLMEvent(L"OnResuming()"); + m_sample->OnResuming(); + } + + void OnResourceAvailabilityChanged(Platform::Object^ sender, Platform::Object^ args) + { + switch (CoreApplication::ResourceAvailability) + { + case ResourceAvailability::FullWithExtendedSystemReserve : + m_sample->LogPLMEvent(L"OnResourceAvailabilityChanged()", L"FullWithExtendedSystemReserve"); break; + case ResourceAvailability::Full: + m_sample->LogPLMEvent(L"OnResourceAvailabilityChanged()", L"Full"); break; + case ResourceAvailability::Constrained: + m_sample->LogPLMEvent(L"OnResourceAvailabilityChanged()", L"Constrained"); break; + default: + break; + } + } + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + if (args->Visible) + { + m_sample->LogPLMEvent(L"OnVisibilityChanged()", L"Visible"); + } + else + { + m_sample->LogPLMEvent(L"OnVisibilityChanged()", L"Not Visible"); + } + } + + void OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args) + { + switch (args->WindowActivationState) + { + case CoreWindowActivationState::CodeActivated : + m_sample->LogPLMEvent(L"OnWindowActivated()", L"CodeActivated"); break; + case CoreWindowActivationState::PointerActivated : + m_sample->LogPLMEvent(L"OnWindowActivated()", L"PointerActivated"); break; + case CoreWindowActivationState::Deactivated : + m_sample->LogPLMEvent(L"OnWindowActivated()", L"Deactivated"); break; + default: + break; + } + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Package.appxmanifest b/XDKSamples/System/SimplePLM/SimplePLM/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..767c0618eb769b91685aaa92e1bc5d353b39b36e --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/Package.appxmanifest @@ -0,0 +1,61 @@ + + + + + + + SimplePLM + Xbox Advanced Technology Group + Assets\StoreLogo.png + SimplePLM + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + variable + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.cpp b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f68d15d300b939dc92538408a351a561267d50db --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.cpp @@ -0,0 +1,234 @@ +//-------------------------------------------------------------------------------------- +// SimplePLM.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimplePLM.h" + +#include "ATGColors.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() : + m_useDeferral(false), + m_consoleIsValid(false), + m_frame(0) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + m_console = std::make_unique(); +} + +void Sample::ShowInstructions() +{ + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Simple PLM")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Launch Settings with A button")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Toggle suspend deferral with B button (default is off)")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Show AccountPicker with X button")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Perform a RestartAplicationOnly with Y button")); +} + +void Sample::LogPLMEvent(const wchar_t* primaryLog, const wchar_t* secondaryData) +{ + unsigned int tid = GetCurrentThreadId(); + SYSTEMTIME curTime; + GetSystemTime(&curTime); + + wchar_t timeAndTid[25]; + swprintf_s(timeAndTid, L"[%02d:%02d:%02d:%03d](%d)", curTime.wHour, curTime.wMinute, curTime.wSecond, curTime.wMilliseconds, tid); + Platform::String^ LogLine = ref new Platform::String(timeAndTid) + " " + ref new Platform::String(primaryLog) + " " + ref new Platform::String(secondaryData); + + //Output to Debug Console. + OutputDebugStringW(LogLine->Data()); + OutputDebugStringW(L"\n"); + + //Output to screen. We must cache screen logs if a log occurs when there is no valid screen console yet. + if (!m_consoleIsValid) + { + m_logCache.insert(m_logCache.begin(), LogLine); + } + else + { + m_console->WriteLine(LogLine->Data()); + } +} + +void Sample::ToggleDeferral() +{ + m_useDeferral = !m_useDeferral; + if (m_useDeferral) + { + LogPLMEvent(L"Will use a suspend deferral."); + } + else + { + LogPLMEvent(L"Will not use a suspend deferral."); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + ToggleDeferral(); + } + if (m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + LogPLMEvent(L"Performing a Restart"); + Windows::ApplicationModel::Core::CoreApplication::RestartApplicationOnly("Restart", nullptr); + } + if (m_gamePadButtons.x == GamePad::ButtonStateTracker::PRESSED) + { + LogPLMEvent(L"Showing AccountPicker"); + Windows::Xbox::UI::SystemUI::ShowAccountPickerAsync(nullptr, Windows::Xbox::UI::AccountPickerOptions::None); + } + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + LogPLMEvent(L"Launching into Settings"); + Windows::System::Launcher::LaunchUriAsync(ref new Windows::Foundation::Uri(L"settings:")); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + m_console->Render(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_console->RestoreDevice(m_deviceResources->GetD3DDeviceContext(), L"Courier_16.spritefont", L"ATGSampleBackground.DDS"); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + m_console->SetWindow(m_deviceResources->GetOutputSize(), true); + //Now that the Console is valid we can flush any logs to the console. + m_consoleIsValid = true; + while (!m_logCache.empty()) + { + m_console->WriteLine(m_logCache.back()->Data()); + m_logCache.pop_back(); + } +} +#pragma endregion diff --git a/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.h b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.h new file mode 100644 index 0000000000000000000000000000000000000000..c5599a09a07b698e2f32d68ecefba3cc78f789fe --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// SimplePLM.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + +#include "TextConsole.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + + //SampleFunctions + void ShowInstructions(); + void LogPLMEvent(const wchar_t* primaryLog, const wchar_t* secondaryData = L""); + bool GetUseDeferral() { return m_useDeferral; } + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Sample Specific + void ToggleDeferral(); + + std::unique_ptr m_console; + bool m_useDeferral; + bool m_consoleIsValid; + std::vector m_logCache; +}; diff --git a/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.vcxproj b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..f7de21ce7f66bec413fcf3f1c5571e108028af60 --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.vcxproj @@ -0,0 +1,217 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SimplePLM + {57402841-95ad-4a7c-8821-f01f8356ccc7} + en-US + Win32Proj + title + + v140 + 14.0 + Native + SimplePLM + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.vcxproj.filters b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..6602cb181c90746aaa60e5c72ac1d83d5a8be64e --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/SimplePLM.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + be6b11ab-b656-4153-88c1-4cebb8a4e05a + + + 51f71cc1-3746-47ee-8537-5b159b8ace38 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {026a0397-f959-40bf-96cd-e46fa2691349} + + + {bd6987b4-f6d4-406d-8215-939cd7b800a7} + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Media + + + + + Media + + + + \ No newline at end of file diff --git a/XDKSamples/System/SimplePLM/SimplePLM/StepTimer.h b/XDKSamples/System/SimplePLM/SimplePLM/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/SimplePLM/SimplePLM/Telemetry.h b/XDKSamples/System/SimplePLM/SimplePLM/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/SimplePLM/SimplePLM/pch.cpp b/XDKSamples/System/SimplePLM/SimplePLM/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/SimplePLM/SimplePLM/pch.h b/XDKSamples/System/SimplePLM/SimplePLM/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..6b8c94117616003f289b205e8166f3482ec08f0f --- /dev/null +++ b/XDKSamples/System/SimplePLM/SimplePLM/pch.h @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/System/SystemInfo/Assets/Logo.png b/XDKSamples/System/SystemInfo/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c306872744549af27d3e096a1c69a4e142c1be02 Binary files /dev/null and b/XDKSamples/System/SystemInfo/Assets/Logo.png differ diff --git a/XDKSamples/System/SystemInfo/Assets/SmallLogo.png b/XDKSamples/System/SystemInfo/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d3455ab22f9ca9d7d796c98ef6ab6e6b9ec6145 Binary files /dev/null and b/XDKSamples/System/SystemInfo/Assets/SmallLogo.png differ diff --git a/XDKSamples/System/SystemInfo/Assets/SplashScreen.png b/XDKSamples/System/SystemInfo/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4f302e4f0b6ab450844393333bcd11c6ba1d40 Binary files /dev/null and b/XDKSamples/System/SystemInfo/Assets/SplashScreen.png differ diff --git a/XDKSamples/System/SystemInfo/Assets/StoreLogo.png b/XDKSamples/System/SystemInfo/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/System/SystemInfo/Assets/StoreLogo.png differ diff --git a/XDKSamples/System/SystemInfo/Assets/WideLogo.png b/XDKSamples/System/SystemInfo/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f4406b31e3f875a068c8b63ae3dac0805fff2ec Binary files /dev/null and b/XDKSamples/System/SystemInfo/Assets/WideLogo.png differ diff --git a/XDKSamples/System/SystemInfo/DeviceResources.cpp b/XDKSamples/System/SystemInfo/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9ffbb6b9d065941a609390393833d7513777f1e --- /dev/null +++ b/XDKSamples/System/SystemInfo/DeviceResources.cpp @@ -0,0 +1,222 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, unsigned int flags) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080}, + m_options(flags) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + D3D11X_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D11_SDK_VERSION; + +#ifdef _DEBUG + // Enable the debug layer. + params.Flags = D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + // Enable the instrumented driver. + params.Flags = D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_options & c_FastSemantics) + { + params.Flags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + // Create the Direct3D 11 API device object and a corresponding context. + ThrowIfFailed(D3D11XCreateDeviceX( + ¶ms, + m_d3dDevice.ReleaseAndGetAddressOf(), + m_d3dContext.ReleaseAndGetAddressOf() + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_options & c_FastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if ((m_options & c_FastSemantics) != 0 && decompressFlags != 0) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/System/SystemInfo/DeviceResources.h b/XDKSamples/System/SystemInfo/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..0c4c4f36247f9a8ea4367769d8d5b92726f9fe3e --- /dev/null +++ b/XDKSamples/System/SystemInfo/DeviceResources.h @@ -0,0 +1,70 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + static const unsigned int c_FastSemantics = 0x1; + + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + unsigned int flags = 0); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + unsigned int GetDeviceOptions() const { return m_options; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + // DeviceResources options (see flags above) + unsigned int m_options; + }; +} \ No newline at end of file diff --git a/XDKSamples/System/SystemInfo/Main.cpp b/XDKSamples/System/SystemInfo/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c747129d9041bf0f160aba020f8e5d6a4ec26f1 --- /dev/null +++ b/XDKSamples/System/SystemInfo/Main.cpp @@ -0,0 +1,147 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SystemInfo.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += + ref new TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + Windows::ApplicationModel::Core::CoreApplication::DisableKinectGpuReservation = true; + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/System/SystemInfo/Package.appxmanifest b/XDKSamples/System/SystemInfo/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..ad28d2deb6e466cf3a15b6932b04deeecd0508be --- /dev/null +++ b/XDKSamples/System/SystemInfo/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SystemInfo + Xbox Advanced Technology Group + Assets\StoreLogo.png + SystemInfo + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/System/SystemInfo/Readme.docx b/XDKSamples/System/SystemInfo/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..37cd69a82bf588b1a7725a108317770517fef491 Binary files /dev/null and b/XDKSamples/System/SystemInfo/Readme.docx differ diff --git a/XDKSamples/System/SystemInfo/StepTimer.h b/XDKSamples/System/SystemInfo/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/System/SystemInfo/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/System/SystemInfo/SystemInfo.cpp b/XDKSamples/System/SystemInfo/SystemInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4566597c79c957b2d3222cbc53bf2dbb3e9e9f1 --- /dev/null +++ b/XDKSamples/System/SystemInfo/SystemInfo.cpp @@ -0,0 +1,374 @@ +//-------------------------------------------------------------------------------------- +// SystemInfo.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SystemInfo.h" + +#include "ATGColors.h" +#include "ControllerFont.h" + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +namespace +{ + inline float XM_CALLCONV DrawStringCenter(SpriteBatch* batch, SpriteFont* font, const wchar_t* text, float mid, float y, FXMVECTOR color, float scale) + { + XMVECTOR size = font->MeasureString(text); + XMFLOAT2 pos(mid - XMVectorGetX(size)*scale / 2.f, y); + font->DrawString(batch, text, pos, color, 0.f, Vector2::Zero, scale); + return font->GetLineSpacing() * scale; + } + + inline void DrawStringLeft(SpriteBatch* batch, SpriteFont* font, const wchar_t* text, float mid, float y, float scale) + { + XMVECTOR size = font->MeasureString(text); + XMFLOAT2 pos(mid - XMVectorGetX(size)*scale, y); + font->DrawString(batch, text, pos, ATG::Colors::Blue, 0.f, Vector2::Zero, scale); + } + + inline float DrawStringRight(SpriteBatch* batch, SpriteFont* font, const wchar_t* text, float mid, float y, float scale) + { + XMFLOAT2 pos(mid, y); + font->DrawString(batch, text, pos, ATG::Colors::White, 0.f, Vector2::Zero, scale); + return font->GetLineSpacing()*scale; + } +} + +Sample::Sample() : + m_frame(0), + m_scale(1.25f), + m_current(0) +{ + // Renders only 2D, so no need for a depth buffer. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED + || m_gamePadButtons.dpadRight == GamePad::ButtonStateTracker::PRESSED) + { + ++m_current; + if (m_current >= int(InfoPage::MAX)) + m_current = 0; + } + + if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED + || m_gamePadButtons.dpadLeft == GamePad::ButtonStateTracker::PRESSED) + { + --m_current; + if (m_current < 0) + m_current = int(InfoPage::MAX) - 1; + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + auto fullscreen = m_deviceResources->GetOutputSize(); + + auto safeRect = Viewport::ComputeTitleSafeArea(fullscreen.right - fullscreen.left, fullscreen.bottom - fullscreen.top); + + float mid = float(safeRect.left) + float(safeRect.right - safeRect.left) / 2.f; + + m_batch->Begin(); + m_batch->Draw(m_background.Get(), fullscreen); + + float y = float(safeRect.top); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.bottom) - m_smallFont->GetLineSpacing()); + + DX::DrawControllerString(m_batch.get(), m_smallFont.get(), m_ctrlFont.get(), L"Use [A], [B], or [DPad] to cycle pages", pos, ATG::Colors::LightGrey, m_scale); + + float spacer = XMVectorGetX(m_smallFont->MeasureString(L"X")*m_scale); + + float left = mid - spacer; + float right = mid + spacer; + + switch (static_cast(m_current)) + { + case InfoPage::SYSTEMINFO: + { + y += DrawStringCenter(m_batch.get(), m_largeFont.get(), L"GetNativeSystemInfo", mid, y, ATG::Colors::LightGrey, m_scale); + + SYSTEM_INFO info = {}; + GetNativeSystemInfo(&info); + + wchar_t buff[128] = { 0 }; + swprintf_s(buff, L"%zX", info.dwActiveProcessorMask); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"dwActiveProcessorMask", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + + swprintf_s(buff, L"%u", info.dwNumberOfProcessors); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"dwNumberOfProcessors", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + + if (info.dwNumberOfProcessors > 6) + { + y += m_smallFont->GetLineSpacing(); + + DrawStringCenter(m_batch.get(), m_smallFont.get(), L"7th Core enabled", mid, y, ATG::Colors::Orange, m_scale); + } + } + break; + + case InfoPage::GLOBALMEMORYSTATUS: + { + y += DrawStringCenter(m_batch.get(), m_largeFont.get(), L"GlobalMemoryStatusEx", mid, y, ATG::Colors::LightGrey, m_scale); + + MEMORYSTATUSEX info = {}; + info.dwLength = sizeof(MEMORYSTATUSEX); + if (GlobalMemoryStatusEx(&info)) + { + auto tphys = static_cast(info.ullTotalPhys / (1024 * 1024)); + auto aphys = static_cast(info.ullAvailPhys / (1024 * 1024)); + auto tvirt = static_cast(info.ullTotalVirtual / (1024 * 1024)); + auto avirt = static_cast(info.ullAvailVirtual / (1024 * 1024)); + + wchar_t buff[128] = { 0 }; + swprintf_s(buff, L"%u / %u (MB)", aphys, tphys); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"Physical Memory", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + + swprintf_s(buff, L"%u (MB)", tvirt); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"Total Virtual Memory", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + + swprintf_s(buff, L"%u (MB)", avirt); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"Available VM", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + } + } + break; + + case InfoPage::ANALYTICSINFO: + { + y += DrawStringCenter(m_batch.get(), m_largeFont.get(), L"AnalyticsInfo", mid, y, ATG::Colors::LightGrey, m_scale); + + auto versionInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo; + + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"DeviceFamily", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), versionInfo->DeviceFamily->Data(), right, y, m_scale); + + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"DeviceFamilyVersion (Title OS)", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), versionInfo->DeviceFamilyVersion->Data(), right, y, m_scale); + + // For real-world use just log it as an opaque string, and do the decode in the reader instead + LARGE_INTEGER li; + li.QuadPart = _wtoi64(versionInfo->DeviceFamilyVersion->Data()); + + wchar_t buff[16] = {}; + swprintf_s(buff, L"%u.%u.%u.%u", HIWORD(li.HighPart), LOWORD(li.HighPart), HIWORD(li.LowPart), LOWORD(li.LowPart)); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + + // The _XDK_VER captures at compile-time the version of the Xbox One XDK used to build the application + y += m_smallFont->GetLineSpacing() * 2; + + swprintf_s(buff, L"%u.%u", HIWORD(_XDK_VER), LOWORD(_XDK_VER)); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"_XDK_VER", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + + if (li.LowPart != _XDK_VER) + { + y += DrawStringCenter(m_batch.get(), m_smallFont.get(), L"Title OS vs. Xbox One XDK mismatch", mid, y, ATG::Colors::Orange, m_scale); + } + } + break; + + case InfoPage::DIRECT3D: + { + y += DrawStringCenter(m_batch.get(), m_largeFont.get(), L"Direct3D", mid, y, ATG::Colors::LightGrey, m_scale); + + auto device = m_deviceResources->GetD3DDevice(); + + D3D11X_GPU_HARDWARE_CONFIGURATION hwConfig = {}; + device->GetGpuHardwareConfiguration(&hwConfig); + + wchar_t buff[128] = { 0 }; + swprintf_s(buff, L"%I64u", hwConfig.GpuFrequency); + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"GPU Frequency", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), buff, right, y, m_scale); + +#if _XDK_VER >= 0x38390868 /* XDK Edition 161000 */ + const wchar_t* hwver = L"Unknown"; + switch (hwConfig.HardwareVersion) + { + case D3D11X_HARDWARE_VERSION_XBOX_ONE: hwver = L"Xbox One"; break; + case D3D11X_HARDWARE_VERSION_XBOX_ONE_S: hwver = L"Xbox One S"; break; +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + case D3D11X_HARDWARE_VERSION_XBOX_ONE_X: hwver = L"Xbox One X"; break; + case D3D11X_HARDWARE_VERSION_XBOX_ONE_X_DEVKIT: hwver = L"Xbox One X (DevKit)"; break; +#endif + } + + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"Hardware Version", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), hwver, right, y, m_scale); +#endif + +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + y += m_smallFont->GetLineSpacing() * 2; + + const wchar_t* conType = L"Unknown"; + switch (GetConsoleType()) + { + case CONSOLE_TYPE_XBOX_ONE: conType = L"Xbox One"; break; + case CONSOLE_TYPE_XBOX_ONE_S: conType = L"Xbox One S"; break; + case CONSOLE_TYPE_XBOX_ONE_X: conType = L"Xbox One X"; break; + case CONSOLE_TYPE_XBOX_ONE_X_DEVKIT: conType = L"Xbox One X (DevKit)"; break; + } + + DrawStringLeft(m_batch.get(), m_smallFont.get(), L"Console Type", left, y, m_scale); + y += DrawStringRight(m_batch.get(), m_smallFont.get(), conType, right, y, m_scale); +#endif + } + break; + } + + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + auto context = m_deviceResources->GetD3DDeviceContext(); + + m_batch = std::make_unique(context); + + m_smallFont = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_largeFont = std::make_unique(device, L"SegoeUI_36.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneControllerLegendSmall.spritefont"); + + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto vp = m_deviceResources->GetScreenViewport(); + m_batch->SetViewport(vp); +} +#pragma endregion diff --git a/XDKSamples/System/SystemInfo/SystemInfo.h b/XDKSamples/System/SystemInfo/SystemInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..f5d1f2e41793fa05a37ab2f781ef8fb66e01bf4d --- /dev/null +++ b/XDKSamples/System/SystemInfo/SystemInfo.h @@ -0,0 +1,76 @@ +//-------------------------------------------------------------------------------------- +// SystemInfo.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // UI + std::unique_ptr m_batch; + std::unique_ptr m_smallFont; + std::unique_ptr m_largeFont; + std::unique_ptr m_ctrlFont; + float m_scale; + + Microsoft::WRL::ComPtr m_background; + + enum class InfoPage + { + SYSTEMINFO = 0, + GLOBALMEMORYSTATUS, + ANALYTICSINFO, + DIRECT3D, + MAX, + }; + + int m_current; +}; diff --git a/XDKSamples/System/SystemInfo/SystemInfo.sln b/XDKSamples/System/SystemInfo/SystemInfo.sln new file mode 100644 index 0000000000000000000000000000000000000000..4b3bd0206467f4d64e11c27427a31dfa705f7005 --- /dev/null +++ b/XDKSamples/System/SystemInfo/SystemInfo.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SystemInfo", "SystemInfo.vcxproj", "{A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Debug|Durango.ActiveCfg = Debug|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Debug|Durango.Build.0 = Debug|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Debug|Durango.Deploy.0 = Debug|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Profile|Durango.ActiveCfg = Profile|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Profile|Durango.Build.0 = Profile|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Profile|Durango.Deploy.0 = Profile|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Release|Durango.ActiveCfg = Release|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Release|Durango.Build.0 = Release|Durango + {A5254D60-5AF4-4B6B-83F1-E38DC0649AD7}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/System/SystemInfo/SystemInfo.vcxproj b/XDKSamples/System/SystemInfo/SystemInfo.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..b6fb3475be54fe189990be1aebdf46a3f7b6bf30 --- /dev/null +++ b/XDKSamples/System/SystemInfo/SystemInfo.vcxproj @@ -0,0 +1,225 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SystemInfo + {a5254d60-5af4-4b6b-83f1-e38dc0649ad7} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;%(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + + + + + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/System/SystemInfo/SystemInfo.vcxproj.filters b/XDKSamples/System/SystemInfo/SystemInfo.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..20703ce8fe13de844d4ad0e0c8b33bd654fe27db --- /dev/null +++ b/XDKSamples/System/SystemInfo/SystemInfo.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + 5d62ec50-cde9-42e9-bb00-70157b8e358d + + + d3ac40bd-92fe-482e-9927-33fd3292a1de + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {fcb7c0c3-e3c3-446f-bf66-4907b13164d3} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/System/SystemInfo/Telemetry.h b/XDKSamples/System/SystemInfo/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/System/SystemInfo/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/System/SystemInfo/pch.cpp b/XDKSamples/System/SystemInfo/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/System/SystemInfo/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/System/SystemInfo/pch.h b/XDKSamples/System/SystemInfo/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..dcf7b05f4099c70617f5b0d42198b048a26add81 --- /dev/null +++ b/XDKSamples/System/SystemInfo/pch.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38390403 /* XDK Edition 160800 */ +#error This sample requires the August 2016 XDK or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "DDSTextureLoader.h" +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Tools/DumpTool/DumpTool.cpp b/XDKSamples/Tools/DumpTool/DumpTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59114990077a2a62dc16ffd41f49f307fcab8d39 --- /dev/null +++ b/XDKSamples/Tools/DumpTool/DumpTool.cpp @@ -0,0 +1,492 @@ +//-------------------------------------------------------------------------------------- +// DumpTool.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include + +#include "CommandLineHelpers.h" +#include "FileHelpers.h" +#include "OSHelpers.h" + +using namespace ATG; + +#define HEX_FMT L"0x%08x" + +namespace +{ + enum options : uint32_t + { + OPT_MINI_DUMP_TYPE = 1, + OPT_PREDEFINED_TYPE, + OPT_MAX + }; + + static_assert(OPT_MAX <= sizeof(options) * 8, "Options must fit into a sizeof(options) * 8 bitfield"); + + const SValue g_Options[] = + { + { L"mdt", OPT_MINI_DUMP_TYPE }, + { L"pdt", OPT_PREDEFINED_TYPE } + }; + +#define DEF_MDT(mdt) { L#mdt, MiniDump ## mdt } + const SValue g_MDTs[] = + { + DEF_MDT(Normal), + DEF_MDT(WithDataSegs), + DEF_MDT(WithFullMemory), + DEF_MDT(WithHandleData), + DEF_MDT(FilterMemory), + DEF_MDT(ScanMemory), + DEF_MDT(WithUnloadedModules), + DEF_MDT(WithIndirectlyReferencedMemory), + DEF_MDT(FilterModulePaths), + DEF_MDT(WithProcessThreadData), + DEF_MDT(WithPrivateReadWriteMemory), + DEF_MDT(WithoutOptionalData), + DEF_MDT(WithFullMemoryInfo), + DEF_MDT(WithThreadInfo), + DEF_MDT(WithCodeSegs), + DEF_MDT(WithoutAuxiliaryState), + DEF_MDT(WithFullAuxiliaryState), + DEF_MDT(WithPrivateWriteCopyMemory), + DEF_MDT(IgnoreInaccessibleMemory), + DEF_MDT(WithTokenInformation), + DEF_MDT(WithModuleHeaders), + DEF_MDT(FilterTriage) + }; +#undef DEF_MDT + + const SValue g_PDTS[] = + { + { L"heap", + MiniDumpWithDataSegs + | MiniDumpWithProcessThreadData + | MiniDumpWithHandleData + | MiniDumpWithPrivateReadWriteMemory + | MiniDumpWithUnloadedModules + | MiniDumpWithPrivateWriteCopyMemory + | MiniDumpWithFullMemoryInfo + | MiniDumpWithThreadInfo + | MiniDumpWithTokenInformation + | MiniDumpIgnoreInaccessibleMemory }, + + { L"mini", + MiniDumpWithDataSegs + | MiniDumpWithUnloadedModules + | MiniDumpWithProcessThreadData + | MiniDumpWithTokenInformation + | MiniDumpIgnoreInaccessibleMemory }, + + { L"micro", + MiniDumpFilterMemory + | MiniDumpFilterModulePaths + | MiniDumpIgnoreInaccessibleMemory }, + + { L"triage", + MiniDumpWithHandleData + | MiniDumpWithUnloadedModules + | MiniDumpFilterModulePaths + | MiniDumpWithProcessThreadData + | MiniDumpFilterTriage + | MiniDumpIgnoreInaccessibleMemory + }, + + { L"native", + MiniDumpWithFullMemory + | MiniDumpWithHandleData + | MiniDumpWithUnloadedModules + | MiniDumpWithFullMemoryInfo + | MiniDumpWithThreadInfo + | MiniDumpWithTokenInformation + | MiniDumpIgnoreInaccessibleMemory } + }; + + void PrintLogo() + { + wprintf(L"Microsoft (R) Minidump tool for for Xbox One\n"); + wprintf(L"Copyright (C) Microsoft Corp. All rights reserved.\n"); +#ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); +#endif + wprintf(L"\n"); + } + + void PrintUsage() + { + PrintLogo(); + + wprintf(L"Usage: DumpTool [-mdt: ...] [-pdt:] \n\n"); + + const wchar_t mdts[] = L"\n : "; + wprintf(mdts); + PrintTable(_countof(mdts) - 2, g_MDTs); + + const wchar_t pdts[] = L"\n : "; + wprintf(pdts); + PrintTable(_countof(pdts) - 2, g_PDTS); + } + +#if defined(_XBOX_ONE) && defined(_TITLE) +#else + BOOL EnableDebugPrivilege(BOOL bEnable) + { + HANDLE hToken = nullptr; + LUID luid; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE; + if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE; + + TOKEN_PRIVILEGES tokenPriv; + tokenPriv.PrivilegeCount = 1; + tokenPriv.Privileges[0].Luid = luid; + tokenPriv.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + + if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE; + + return TRUE; + } +#endif + + inline HANDLE safe_proc_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } + + class CProcHandle + { + HANDLE m_handle; + public: + + CProcHandle() + : CProcHandle(0) + { + } + + CProcHandle(HANDLE h) + : m_handle(safe_proc_handle(h)) + { + } + + CProcHandle(const CProcHandle &) = delete; + CProcHandle &operator=(const CProcHandle &) = delete; + + CProcHandle(CProcHandle &&other) + : m_handle(other.detach()) + { + } + + + CProcHandle &operator=(CProcHandle &&other) + { + close(); + m_handle = other.m_handle; + other.m_handle = nullptr; + return *this; + } + + ~CProcHandle() + { + close(); + } + + + operator bool() const + { + return m_handle != nullptr; + } + + HANDLE get() const + { + return m_handle; + } + + HANDLE detach() + { + HANDLE result = m_handle; + m_handle = nullptr; + return result; + } + + void close() + { + assert(m_handle != INVALID_HANDLE_VALUE); + if (m_handle) + { + CloseHandle(m_handle); + } + } + }; + + bool FileExists(const wchar_t *fileName) + { + uint32_t attrs = ::GetFileAttributesW(fileName); + + return (attrs != INVALID_FILE_ATTRIBUTES + && !(attrs & FILE_ATTRIBUTE_DIRECTORY)); + } + + wchar_t *GetDumpFileName(const wchar_t *exeName) + { + static wchar_t outFile[MAX_PATH] = L"d:\\"; + { + wcscat_s(outFile, exeName); + + wchar_t *dot = wcsrchr(outFile, '.'); + if (dot) + { + *dot = L'\0'; + } + wcscat_s(outFile, L".dmp"); + + int num = 1; + wchar_t suffix[16] = L""; + + wchar_t *underscore = dot; + while (FileExists(outFile)) + { + *underscore = L'\0'; + swprintf_s(suffix, L"_%i.dmp", ++num); + wcscat_s(outFile, suffix); + } + } + + return outFile; + } + + void WriteDump(HANDLE proc, DWORD procId, MINIDUMP_TYPE mdt, const wchar_t *dumpFileName) + { + if (!dumpFileName) + { + DX::ThrowIfFailed(E_INVALIDARG); + } + + wprintf(L"Writing dump file: %s (type: 0x%08x)\n", dumpFileName, mdt); + + // Create the dump file + ScopedHandle dumpFile(safe_handle( + CreateFile( + dumpFileName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL))); + + if (!dumpFile) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + + if (!MiniDumpWriteDump(proc, procId, dumpFile.get(), mdt, nullptr, nullptr, nullptr)) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + + if (!FlushFileBuffers(dumpFile.get())) + { + DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + } + } + + void WriteDumpForFileName(const wchar_t *filename, MINIDUMP_TYPE mdt) + { + int processCount = 0; + DWORD procIds[256]; + { + DWORD resultSize = 0; + if (EnumProcesses(procIds, sizeof(procIds), &resultSize)) + { + processCount = resultSize / sizeof(DWORD); + wchar_t buf[64] = L""; + swprintf_s(buf, L"Found %i processes\n", processCount); + OutputDebugString(buf); + } + else + { + auto err = GetLastError(); + wchar_t buf[64] = L""; + swprintf_s(buf, L"EnumProcesses failed with error code:" HEX_FMT L"\n", err); + OutputDebugString(buf); + DX::ThrowIfFailed(HRESULT_FROM_WIN32(err)); + } + } + + CProcHandle proc; + + for (int i = 0; i < processCount; ++i) + { + proc = OpenProcess(PROCESS_ALL_ACCESS, true, procIds[i]); + if (proc) + { + wchar_t procName[MAX_PATH]; + + size_t nameLength = GetProcessImageFileName(proc.get(), procName, MAX_PATH); + auto err = (nameLength == 0) ? GetLastError() : 0; + + if (err) + { + wchar_t buf[64] = L""; + swprintf_s(buf, L"GetProcessImageFileName failed with error code:" HEX_FMT L"\n", err); + OutputDebugString(buf); + } + else + { + procName[MAX_PATH - 1] = 0; + wchar_t *fn = wcsrchr(procName, L'\\'); + fn = fn ? fn + 1 : procName; + + if (_wcsicmp(fn, filename) == 0) + { + WriteDump(proc.get(), procIds[i], mdt, GetDumpFileName(fn)); + return; + } + } + } + else + { + auto err = GetLastError(); + wchar_t buf[64] = L""; + swprintf_s(buf, L"OpenProcess failed with error code:" HEX_FMT L"\n", err); + OutputDebugString(buf); + continue; + } + } + + wprintf(L"Could not find executable: %s\n", filename); + } + + +} // ANONYMOUS namespace + +int wmain(int argc, wchar_t **argv) +{ + // These will be filled in during argument parsing + unsigned mdt = MiniDumpNormal; + unsigned oneMdt = MiniDumpNormal; + unsigned pdt = MiniDumpNormal; + const wchar_t *exeName = nullptr; + + unsigned individualOptions = 0; + + // Starting at 1 to skip the name of *this* executable + for (int argIdx = 1; argIdx < argc; ++argIdx) + { + wchar_t *arg = argv[argIdx]; + + if (('-' == arg[0]) || ('/' == arg[0])) + { + arg++; + + // This voodoo will separate the option from the corresponding value: + wchar_t *value = nullptr; + for (value = arg; *value && (':' != *value); ++value); + if (*value) *value++ = 0; + + // Lookup the option part + unsigned option = 0; + if (!LookupByName(arg, g_Options, option) || (individualOptions & (1 << option))) + { + if (individualOptions & (1 << option)) + { + wprintf(L"The option, -%s, can only be specified once\n\n", arg); + } + PrintUsage(); + return 1; + } + + // Keep track of uses of individual options + if (option != OPT_MINI_DUMP_TYPE) + { + individualOptions |= (1 << option); + } + + // Handle options that consume an additional argument + switch (option) + { + case OPT_MINI_DUMP_TYPE: + case OPT_PREDEFINED_TYPE: + if (!*value) + { + if (argIdx + 1 >= argc) + { + PrintUsage(); + return 1; + } + + ++argIdx; + value = argv[argIdx]; + } + break; + } + + switch (option) + { + case OPT_MINI_DUMP_TYPE: + if (ParseTableValue(option, value, g_MDTs, oneMdt)) + { + mdt |= oneMdt; + } + else + { + PrintUsage(); + return 1; + } + break; + + case OPT_PREDEFINED_TYPE: + if (ParseTableValue(option, value, g_PDTS, pdt)) + { + mdt |= pdt; + } + else + { + PrintUsage(); + return 1; + } + } + } + else + { + if (exeName == nullptr) + { + exeName = arg; + } + else + { + wprintf(L" already has a value (%s). Found another one: %s\n\n", exeName, arg); + PrintUsage(); + return 1; + } + } + } + + if (exeName == nullptr) + { + wprintf(L" was not specified.\n\n"); + PrintUsage(); + return 1; + } + + try + { +#if defined(_XBOX_ONE) && defined(_TITLE) +#else + EnableDebugPrivilege(true); +#endif + WriteDumpForFileName(exeName, (MINIDUMP_TYPE)mdt); + } + catch (std::exception exn) + { + wprintf(L"Failed to write dump:\n%S\n", exn.what()); + } + catch (...) + { + wprintf(L"Unexpected failure while attempting to write the dump\n"); + } + + return 0; +} diff --git a/XDKSamples/Tools/DumpTool/DumpTool.sln b/XDKSamples/Tools/DumpTool/DumpTool.sln new file mode 100644 index 0000000000000000000000000000000000000000..7eef7069d9a05c43a69e2f56860f182010393842 --- /dev/null +++ b/XDKSamples/Tools/DumpTool/DumpTool.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DumpTool", "DumpTool.vcxproj", "{EE83F258-D4C7-4AB4-BD6A-71C3643664DE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EE83F258-D4C7-4AB4-BD6A-71C3643664DE}.Debug|Durango.ActiveCfg = Debug|Durango + {EE83F258-D4C7-4AB4-BD6A-71C3643664DE}.Debug|Durango.Build.0 = Debug|Durango + {EE83F258-D4C7-4AB4-BD6A-71C3643664DE}.Release|Durango.ActiveCfg = Release|Durango + {EE83F258-D4C7-4AB4-BD6A-71C3643664DE}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Tools/DumpTool/DumpTool.vcxproj b/XDKSamples/Tools/DumpTool/DumpTool.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..388e1a6d6f0af48b055e60dd86806f4c435dd290 --- /dev/null +++ b/XDKSamples/Tools/DumpTool/DumpTool.vcxproj @@ -0,0 +1,137 @@ + + + + + Debug + Durango + + + Release + Durango + + + + {EE83F258-D4C7-4AB4-BD6A-71C3643664DE} + en-US + Win32Proj + BlankXDKConsole + title + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + false + + + + + + + + + true + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + $(Console_SdkIncludeRoot) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + + *.pdb;*.ilk;*.exp;*.lib;*.winmd;*.appxrecipe;*.pri + + + false + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + $(Console_SdkIncludeRoot) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Platform)\$(Configuration)\ + + + $(Platform)\$(Configuration)\ + + + + Use + pch.h + Level4 + Disabled + _XBOX_ONE;_TITLE;_DEBUG;_CONSOLE;_UNICODE;UNICODE + false + + MultiThreadedDebugDLL + true + ..\..\..\Kits\ATGTK\ + + + Console + true + kernelx.lib;toolhelpx.lib + + $(IgnoreSpecificDefaultLibraries);advapi32.lib;atl.lib;atls.lib;atlsd.lib;atlsn.lib;atlsnd.lib;comctl32.lib;comsupp.lib;dbghelp.lib;gdi32.lib;gdiplus.lib;guardcfw.lib;kernel32.lib;mmc.lib;msimg32.lib;msvcole.lib;msvcoled.lib;mswsock.lib;ntstrsafe.lib;ole2.lib;ole2autd.lib;ole2auto.lib;ole2d.lib;ole2ui.lib;ole2uid.lib;ole32.lib;oleacc.lib;oleaut32.lib;oledlg.lib;oledlgd.lib;oldnames.lib;runtimeobject.lib;shell32.lib;shlwapi.lib;strsafe.lib;urlmon.lib;user32.lib;userenv.lib;uuid.lib;wlmole.lib;wlmoled.lib;ws2_32.lib;msvcrt.lib + + + + + Level4 + Use + pch.h + MaxSpeed + true + true + _XBOX_ONE;_TITLE;NDEBUG;_CONSOLE;_UNICODE;UNICODE + false + + true + ..\..\..\Kits\ATGTK\ + + + Console + true + true + true + kernelx.lib;toolhelpx.lib + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/DumpTool/DumpTool.vcxproj.filters b/XDKSamples/Tools/DumpTool/DumpTool.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..5e30cff18458b60d171092713816939a8a32527a --- /dev/null +++ b/XDKSamples/Tools/DumpTool/DumpTool.vcxproj.filters @@ -0,0 +1,31 @@ + + + + + + + ATGTK + + + + + + ATGTK + + + ATGTK + + + ATGTK + + + + + {e90e6930-6ac7-4099-add1-3d7c1cbc09aa} + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/DumpTool/Readme.docx b/XDKSamples/Tools/DumpTool/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..331f1ada024d9bf54561c164ab45bcd7a8484a4f Binary files /dev/null and b/XDKSamples/Tools/DumpTool/Readme.docx differ diff --git a/XDKSamples/Tools/DumpTool/pch.cpp b/XDKSamples/Tools/DumpTool/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ed11d01f33e3403636eaf5340ce02b6538cdcea --- /dev/null +++ b/XDKSamples/Tools/DumpTool/pch.cpp @@ -0,0 +1,9 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" \ No newline at end of file diff --git a/XDKSamples/Tools/DumpTool/pch.h b/XDKSamples/Tools/DumpTool/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb17ccf22317e92d47944c38b42dc7b7cf27d2b --- /dev/null +++ b/XDKSamples/Tools/DumpTool/pch.h @@ -0,0 +1,49 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include +#include +#include +#include +#include +#include +#include + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Tools/DumpTool/runCommand.bat b/XDKSamples/Tools/DumpTool/runCommand.bat new file mode 100644 index 0000000000000000000000000000000000000000..6b5ce8e72d86ca62552c2b88a687bd9fa85d55d7 --- /dev/null +++ b/XDKSamples/Tools/DumpTool/runCommand.bat @@ -0,0 +1,8 @@ +echo Waiting for a Title process to start +xbconnect /wt + +echo Copy over the current debug version of the tool to the default console +xbcp /x/title Durango\Debug\DumpTool.exe xd:\ + +echo Running the tool with args: %* +xbrun /x/title /O d:\DumpTool -pdt:triage %* diff --git a/XDKSamples/Tools/OSPrimitiveTool/Assets/Logo.png b/XDKSamples/Tools/OSPrimitiveTool/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c0fc7df8cd1c677853b40c147a5a57a0e733cea6 Binary files /dev/null and b/XDKSamples/Tools/OSPrimitiveTool/Assets/Logo.png differ diff --git a/XDKSamples/Tools/OSPrimitiveTool/Assets/SmallLogo.png b/XDKSamples/Tools/OSPrimitiveTool/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c352cc68fce5c0410210abbe08188ef1159ec0d2 Binary files /dev/null and b/XDKSamples/Tools/OSPrimitiveTool/Assets/SmallLogo.png differ diff --git a/XDKSamples/Tools/OSPrimitiveTool/Assets/SplashScreen.png b/XDKSamples/Tools/OSPrimitiveTool/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..96fede95bd502a1bb17ca64976c397455711f69a Binary files /dev/null and b/XDKSamples/Tools/OSPrimitiveTool/Assets/SplashScreen.png differ diff --git a/XDKSamples/Tools/OSPrimitiveTool/Assets/StoreLogo.png b/XDKSamples/Tools/OSPrimitiveTool/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Tools/OSPrimitiveTool/Assets/StoreLogo.png differ diff --git a/XDKSamples/Tools/OSPrimitiveTool/Assets/WideLogo.png b/XDKSamples/Tools/OSPrimitiveTool/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..02ba097439184f85fe04530259c8dab9dc303988 Binary files /dev/null and b/XDKSamples/Tools/OSPrimitiveTool/Assets/WideLogo.png differ diff --git a/XDKSamples/Tools/OSPrimitiveTool/Chunks.xml b/XDKSamples/Tools/OSPrimitiveTool/Chunks.xml new file mode 100644 index 0000000000000000000000000000000000000000..349231be73d41a365b13355da73b881e484f676e --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/Chunks.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/BaseLogger.cpp b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/BaseLogger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..759eeace8d483d5cf9b3196885137517f3a9b27e --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/BaseLogger.cpp @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// BaseLogger.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "BaseLogger.h" + +using namespace ATG; +using namespace DebugLog; + +BaseLogger::BaseLogger() +{ + m_outputQueue[0].reserve(1000); + m_outputQueue[1].reserve(1000); + m_currentOutputQueue = 0; + m_outputThread = nullptr; +} + +BaseLogger::~BaseLogger() +{ + ShutdownLogger(); +} + +void BaseLogger::StartupLogger() +{ + m_killFlag.store(0); + m_outputThread = new std::thread(&BaseLogger::SaveLogThread, this); +} + +void BaseLogger::ShutdownLogger() +{ + if (m_outputThread) + { + m_killFlag.store(1); + m_outputThread->join(); + DumpQueue(m_currentOutputQueue); + DumpQueue(!m_currentOutputQueue); + m_outputThread = nullptr; + } +} + +void BaseLogger::Log(const std::wstring& logLine) +{ + std::lock_guard lg(m_queueCrit); + m_outputQueue[m_currentOutputQueue].emplace(m_outputQueue[m_currentOutputQueue].end(), logLine); +} + +void BaseLogger::SaveLogThread(void) +{ + while (m_killFlag.load() == 0) + { + uint32_t outputQueue = m_currentOutputQueue; + { + std::lock_guard lg(m_queueCrit); + m_currentOutputQueue = !m_currentOutputQueue; + } + DumpQueue(outputQueue); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/BaseLogger.h b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/BaseLogger.h new file mode 100644 index 0000000000000000000000000000000000000000..5bcf8219afe4a26a3835a09b4639a6dfc760c385 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/BaseLogger.h @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------------------- +// BaseLogger.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include +#include +#include + +namespace ATG +{ + namespace DebugLog + { + class BaseLogger + { + protected: + std::thread *m_outputThread; + std::mutex m_queueCrit; + std::vector m_outputQueue[2]; + uint32_t m_currentOutputQueue; + std::atomic m_killFlag; + + void SaveLogThread(void); + virtual void DumpQueue(uint32_t queueIndex) = 0; + virtual void ShutdownLogger(); + virtual void StartupLogger(); + + public: + BaseLogger(const BaseLogger& rhs) = delete; + BaseLogger &operator= (const BaseLogger& rhs) = delete; + BaseLogger(); + virtual ~BaseLogger(); + + void Log(const std::wstring& logLine); + }; + } +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/FileLogger.cpp b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/FileLogger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4970c7ebd02085aea5ecda846640ceba23d7cd29 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/FileLogger.cpp @@ -0,0 +1,106 @@ +//-------------------------------------------------------------------------------------- +// FileLogger.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "FileLogger.h" + +#if defined(_XBOX_ONE) +#include +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#else +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#endif + +using namespace ATG; +using namespace DebugLog; + +FileLogger::FileLogger() : BaseLogger() +{ + m_baseFileName = L""; + m_append = false; + m_streamFile = nullptr; +} +FileLogger::FileLogger(const std::wstring& location, bool append, bool includeCompilerVersion) : BaseLogger() +{ + m_baseFileName = location; + m_append = append; + m_includeCompilerVersion = includeCompilerVersion; + StartupLogger(); +} + +FileLogger::~FileLogger() +{ + ShutdownLogger(); +} + +void FileLogger::OpenLogFile() +{ + std::wstring fullFileName; +#ifdef _XBOX_ONE + fullFileName = L"d:\\"; +#else + _mkdir("Logs"); + fullFileName = L"Logs\\"; +#endif + + fullFileName += m_baseFileName; + if (m_includeCompilerVersion) + { + wchar_t temp[32]; + _itow_s<32>(_MSC_FULL_VER, temp, 10); + fullFileName += L"_"; + fullFileName += temp; + } + fullFileName += L".txt"; + m_fullFileName = fullFileName; + std::ios_base::openmode fred = std::ios_base::out; + if (m_append) + fred += std::ios_base::app; + m_streamFile = new std::basic_fstream(m_fullFileName, fred); +} + +void FileLogger::ShutdownLogger() +{ + BaseLogger::ShutdownLogger(); + delete m_streamFile; + m_streamFile = nullptr; +} + +void FileLogger::StartupLogger() +{ + OpenLogFile(); + BaseLogger::StartupLogger(); +} + +bool FileLogger::ResetLogFile(const std::wstring& location, bool append, bool includeCompilerVersion) +{ + ShutdownLogger(); + m_baseFileName = location; + m_append = append; + m_includeCompilerVersion = includeCompilerVersion; + StartupLogger(); + return true; +} + +void FileLogger::DumpQueue(uint32_t queueIndex) +{ + std::vector::iterator iter, endIter; + + endIter = m_outputQueue[queueIndex].end(); + for (iter = m_outputQueue[queueIndex].begin(); iter != endIter; ++iter) + { + *m_streamFile << iter->c_str(); + *m_streamFile << std::endl; + } + m_outputQueue[queueIndex].clear(); +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/FileLogger.h b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/FileLogger.h new file mode 100644 index 0000000000000000000000000000000000000000..ef7db5589adb4a68267c95940ee07a266ff20902 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/Libraries/Logging/FileLogger.h @@ -0,0 +1,41 @@ +//-------------------------------------------------------------------------------------- +// FileLogger.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include +#include "BaseLogger.h" + +namespace ATG +{ + namespace DebugLog + { + class FileLogger : public BaseLogger + { + protected: + std::basic_fstream *m_streamFile; + std::wstring m_baseFileName; + std::wstring m_fullFileName; + bool m_append; + bool m_includeCompilerVersion; + + virtual void ShutdownLogger(); + virtual void StartupLogger(); + + virtual void DumpQueue(uint32_t queueIndex); + void OpenLogFile(); + + public: + FileLogger(const FileLogger& rhs) = delete; + FileLogger &operator= (const FileLogger& rhs) = delete; + FileLogger(); + FileLogger(const std::wstring& location, bool append, bool includeCompilerVersion = false); + virtual ~FileLogger(); + bool ResetLogFile(const std::wstring& location, bool append, bool includeCompilerVersion = false); + }; + } +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.sln b/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.sln new file mode 100644 index 0000000000000000000000000000000000000000..615db3fdd5c5f178c77d4e68a8a66348e5923151 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OSPrimitiveToolXbox", "OSPrimitiveToolXbox.vcxproj", "{81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}" + ProjectSection(ProjectDependencies) = postProject + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2} = {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Debug|Durango.ActiveCfg = Debug|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Debug|Durango.Build.0 = Debug|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Debug|Durango.Deploy.0 = Debug|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Profile|Durango.ActiveCfg = Profile|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Profile|Durango.Build.0 = Profile|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Profile|Durango.Deploy.0 = Profile|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Release|Durango.ActiveCfg = Release|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Release|Durango.Build.0 = Release|Durango + {81CEEE3B-9467-4CC4-9C3D-1ECA036733E2}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.vcxproj b/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..1efe639cd49e662444fb06b71764980c66f7c4da --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.vcxproj @@ -0,0 +1,263 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + OSPrimitiveToolXbox + {81ceee3b-9467-4cc4-9c3d-1eca036733e2} + en-US + Win32Proj + title + + v140 + 14.0 + Native + 8.1 + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + *.pdb;*.ilk;*.exp;*.lib;*.winmd;*.appxrecipe;*.ipdb;*.iobj + bin\XboxBuild\$(Configuration)\ + $(SolutionDir)bin\XboxBuild\$(Platform)\$(Configuration)\ + bin\XboxBuild\Layout\ + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + *.pdb;*.ilk;*.exp;*.lib;*.winmd;*.appxrecipe;*.ipdb;*.iobj + bin\XboxBuild\$(Configuration)\ + $(SolutionDir)bin\XboxBuild\$(Platform)\$(Configuration)\ + bin\XboxBuild\Layout\ + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + *.pdb;*.ilk;*.exp;*.lib;*.winmd;*.appxrecipe;*.ipdb;*.iobj + bin\XboxBuild\$(Configuration)\ + $(SolutionDir)bin\XboxBuild\$(Platform)\$(Configuration)\ + bin\XboxBuild\Layout\ + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + true + + + 5.0 + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + + + true + Windows + true + true + false + + + Use + pch.h + Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + true + + + 5.0 + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies); + Windows + true + false + + + pch.h + Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + true + + + 5.0 + + + + + + + + + + + + + + + + + NotUsing + NotUsing + NotUsing + + + NotUsing + NotUsing + NotUsing + + + + + Create + Create + Create + + + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + + + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + + + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + ..;..\Libraries;..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + + + Designer + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.vcxproj.filters b/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..877292a4b6289a48e72ccf06191d2b7ca8597566 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/OSPrimitiveToolXbox.vcxproj.filters @@ -0,0 +1,90 @@ + + + + + b1bebbe1-699b-4610-8d78-82f5a992ba75 + + + 6d095f79-683b-4843-8e3d-bddefc2f415f + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {25ad7249-611b-43b3-a48d-ea09834ba9cf} + + + {f0a8a316-4435-40de-abbd-f96ac33b6b11} + + + + + + Common + + + Common + + + Common + + + + + + Logging + + + Logging + + + ATG Tool Kit + + + + + + Common + + + + + + + Logging + + + Logging + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/OSPrimitiveTool/PerfRun.cpp b/XDKSamples/Tools/OSPrimitiveTool/PerfRun.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59c13412f806671c0c46de6495b48e802c2433e8 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/PerfRun.cpp @@ -0,0 +1,533 @@ +//-------------------------------------------------------------------------------------- +// PerfRun.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "PerfRun.h" +#include "Logging\FileLogger.h" + +PerfRun::PerfRun() : + m_startTestRun(false) + , m_receiverReady(false) + , m_senderReady(false) + , m_receiverDone(false) + , m_senderDone(false) + , m_workerShutdown(false) + , m_senderThread(nullptr) + , m_receiverThread(nullptr) + , m_acquireLogfile(nullptr) + , m_releaseLogFile(nullptr) +{ + m_semaphore = CreateSemaphoreEx(nullptr, 1, 1, nullptr, 0, SEMAPHORE_ALL_ACCESS); + m_event = CreateEvent(nullptr, false, true, nullptr); + m_mutex = CreateMutex(nullptr, false, nullptr); + InitializeSRWLock(&m_srw); + InitializeCriticalSection(&m_critSection); + InitializeConditionVariable(&m_conditionVariable); + m_waitAddress = 0; + + KernelFuncs[PERFORM_SEMAPHORE] = KernelFuncPair(std::bind(ReleaseSemaphore, m_semaphore, 1, nullptr), std::bind(WaitForSingleObject, m_semaphore, INFINITE)); + KernelFuncs[PERFORM_EVENT] = KernelFuncPair(std::bind(SetEvent, m_event), std::bind(WaitForSingleObject, m_event, INFINITE)); + KernelFuncs[PERFORM_MUTEX] = KernelFuncPair(std::bind(ReleaseMutex, m_mutex), std::bind(WaitForSingleObject, m_mutex, INFINITE)); + KernelFuncs[PERFORM_SRW] = KernelFuncPair(std::bind(ReleaseSRWLockExclusive, &m_srw), std::bind(AcquireSRWLockExclusive, &m_srw)); + KernelFuncs[PERFORM_CRITICAL_SECTION] = KernelFuncPair(std::bind(LeaveCriticalSection, &m_critSection), std::bind(EnterCriticalSection, &m_critSection)); + KernelFuncs[PERFORM_WAIT_ADDRESS] = KernelFuncPair(nullptr, nullptr); + KernelFuncs[PERFORM_CONDITION_SRW] = KernelFuncPair(std::bind(ReleaseSRWLockExclusive, &m_srw), std::bind(AcquireSRWLockExclusive, &m_srw)); + KernelFuncs[PERFORM_CONDITION_CS] = KernelFuncPair(std::bind(LeaveCriticalSection, &m_critSection), std::bind(EnterCriticalSection, &m_critSection)); +} + +PerfRun::~PerfRun() +{ + if (m_senderThread) + m_senderThread->join(); + if (m_receiverThread) + m_receiverThread->join(); + delete m_senderThread; + delete m_receiverThread; + CloseHandle(m_semaphore); + CloseHandle(m_event); + CloseHandle(m_mutex); + DeleteCriticalSection(&m_critSection); + delete m_acquireLogfile; + delete m_releaseLogFile; +} + +void PerfRun::OpenLogFiles(bool noContention) +{ + if (m_acquireLogfile == nullptr) + { + std::wstring logName; + if (noContention) + { + logName = L"Primitive_NoContention"; + } + else + { + logName = L"Primitive_Contention"; + } + m_acquireLogfile = new ATG::DebugLog::FileLogger(logName, false); + { + std::wstring textBuffer; + textBuffer = L"Run,Average,Median,Minimum,Maximum,STD,Average us,Median us,Minimum us,Maximum us,STD us,Timings"; + m_acquireLogfile->Log(textBuffer); + } + } + if (m_releaseLogFile == nullptr) + { + std::wstring releaseName; + if (noContention) + { + releaseName = L"Primitive_Release_NoContention"; + } + else + { + releaseName = L"Primitive_Release_Contention"; + } + m_releaseLogFile = new ATG::DebugLog::FileLogger(releaseName, false); + { + std::wstring textBuffer; + textBuffer = L"Run,Average,Median,Minimum,Maximum,STD,Average us,Median us,Minimum us,Maximum us,STD us,Timings"; + m_releaseLogFile->Log(textBuffer); + } + } +} + +void PerfRun::RunTests(uint32_t senderCore, uint32_t receiverCore, TestType whichTest, bool noContention, uint32_t idleWorkers) +{ + OpenLogFiles(noContention); + m_startTestRun = false; + m_receiverReady = false; + m_senderReady = false; + m_receiverDone = false; + m_senderDone = false; + m_senderThread = nullptr; + m_receiverThread = nullptr; + uint64_t processAffinityMask; + uint64_t systemAffinityMask; + GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); + SetThreadAffinityMask(GetCurrentThread(), processAffinityMask & ~(1 << senderCore) & ~(1 << receiverCore)); + + m_workerShutdown = false; + if (idleWorkers > 0) + { + m_workerThreads.clear(); + for (uint32_t i = 0; i < s_MaxCore; i++) + { + for (uint32_t j = 0; j < idleWorkers; j++) + { + m_workerThreads.push_back(new std::thread(&PerfRun::WorkerThread, this, i, THREAD_PRIORITY_NORMAL, ((i == senderCore) || (i == receiverCore)))); + } + } + } + + if (noContention) + { + static std::function NoContentionFunc[] = + { + &PerfRun::ReceiveKernelFunctionNoContention, + &PerfRun::ReceiveKernelFunctionNoContention, + &PerfRun::ReceiveKernelFunctionNoContention, + &PerfRun::ReceiveKernelFunctionNoContention, + &PerfRun::ReceiveKernelFunctionNoContention, + &PerfRun::ReceiveWaitAddressFunctionNoContention, + &PerfRun::ReceiveCVFunctionNoContention, + &PerfRun::ReceiveCVFunctionNoContention, + }; + + receiverCore = senderCore; + m_receiverThread = new std::thread(NoContentionFunc[whichTest], this, whichTest, receiverCore, THREAD_PRIORITY_TIME_CRITICAL); + } + else + { + typedef std::pair, std::function> ContentionPair; + static ContentionPair ContentionFunc[] = + { + ContentionPair(&PerfRun::SendKernelFunction,&PerfRun::ReceiveKernelFunction), + ContentionPair(&PerfRun::SendKernelFunction,&PerfRun::ReceiveKernelFunction), + ContentionPair(&PerfRun::SendKernelFunction,&PerfRun::ReceiveKernelFunction), + ContentionPair(&PerfRun::SendKernelFunction,&PerfRun::ReceiveKernelFunction), + ContentionPair(&PerfRun::SendKernelFunction,&PerfRun::ReceiveKernelFunction), + ContentionPair(&PerfRun::SendWaitAddressFunction,&PerfRun::ReceiveWaitAddressFunction), + ContentionPair(&PerfRun::SendCVFunction,&PerfRun::ReceiveCVFunction), + ContentionPair(&PerfRun::SendCVFunction,&PerfRun::ReceiveCVFunction), + }; + + m_senderThread = new std::thread(ContentionFunc[whichTest].first, this, whichTest, senderCore, THREAD_PRIORITY_TIME_CRITICAL); + m_receiverThread = new std::thread(ContentionFunc[whichTest].second, this, whichTest, receiverCore, THREAD_PRIORITY_TIME_CRITICAL); + } + + for (uint32_t i = 0; i < c_NumTestLoops; i++) + { + m_memoryRaceTimings[i] = 0; + m_releaseTimings[i] = 0; + } + + m_startTestRun = true; + if (!noContention) + m_senderThread->join(); + m_receiverThread->join(); + delete m_senderThread; + delete m_receiverThread; + m_senderThread = nullptr; + m_receiverThread = nullptr; + m_workerShutdown = true; + WakeByAddressAll(&m_workerShutdown); + for (auto thread : m_workerThreads) + { + thread->join(); + delete thread; + } + m_workerThreads.clear(); + + { + std::wstring textBuffer; + std::wstring releaseTextBuffer; + wchar_t tempStr[64]; + swprintf_s(tempStr, 64, L"%s %d-%d-%d,,,,,,,,,,,", ConvertTestTypeToString(whichTest).c_str(), senderCore, receiverCore, idleWorkers); + textBuffer = tempStr; + releaseTextBuffer = tempStr; + for (uint32_t k = 0; k < c_NumTestLoops; k++) + { + uint64_t value = m_memoryRaceTimings[k]; + swprintf_s(tempStr, 64, L"%lld,", value); + textBuffer += tempStr; + + value = m_releaseTimings[k]; + swprintf_s(tempStr, 64, L"%lld,", value); + releaseTextBuffer += tempStr; + } + if (m_acquireLogfile) + m_acquireLogfile->Log(textBuffer); + if (m_releaseLogFile) + m_releaseLogFile->Log(releaseTextBuffer); + } +} + +void PerfRun::WorkerThread(uint32_t core, int32_t priority, bool suspend) +{ + HANDLE curThread = GetCurrentThread(); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriorityBoost(curThread, true); + SetThreadPriority(curThread, priority); + while (!m_workerShutdown) + { + if (suspend) + { + bool waitValue = false; + WaitOnAddress(&m_workerShutdown, &waitValue, 1, INFINITE); + } + else + { + SwitchToThread(); + } + } +} + +void PerfRun::SendKernelFunction(TestType whichTest, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriorityBoost(curThread, true); + SetThreadPriority(curThread, priority); + + KernelFuncs[whichTest].second(); + for (uint32_t i = 0; i < c_NumTestLoops; i++) + { + uint64_t startTime = 0; + uint64_t endTime = 0; + uint32_t tscTime = 0; + uint64_t deltaTime = 0; + + m_senderReady = true; + while (!m_receiverReady); + startTime = __rdtscp(&tscTime); + endTime = __rdtscp(&tscTime); + while ((endTime - startTime) < c_SendDelay) // need to give time for the receive thread to actually suspend waiting on the object. + { + endTime = __rdtscp(&tscTime); + } + m_calcedDelay = endTime - startTime; + startTime = __rdtscp(&tscTime); + KernelFuncs[whichTest].first(); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_releaseTimings[i] = deltaTime; + + while (!m_receiverDone) {} + m_senderReady = false; + m_senderDone = true; + + KernelFuncs[whichTest].second(); + m_senderDone = false; + } + KernelFuncs[whichTest].first(); +} + +void PerfRun::ReceiveKernelFunction(TestType whichTest, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriorityBoost(curThread, true); + SetThreadPriority(curThread, priority); + + for (uint32_t loopCount = 0; loopCount < c_NumTestLoops; loopCount++) + { + m_receiverReady = true; + while (!m_senderReady); + uint64_t startTime = 0; + uint64_t endTime = 0; + uint64_t deltaTime = 0; + uint32_t tscTime = 0; + startTime = __rdtscp(&tscTime); + KernelFuncs[whichTest].second(); + endTime = __rdtscp(&tscTime); + m_receiverReady = false; + m_receiverDone = true; + while (!m_senderDone) {} + deltaTime = endTime - startTime; + m_memoryRaceTimings[loopCount] = (deltaTime < m_calcedDelay) ? 0 : deltaTime - m_calcedDelay; + m_memoryRaceTimingsRaw[loopCount] = deltaTime; + m_memoryRaceTimingsCalcedDelta[loopCount] = m_calcedDelay; + m_receiverDone = false; + KernelFuncs[whichTest].first(); + } +} + +void PerfRun::SendWaitAddressFunction(TestType /*whichTest*/, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriority(curThread, priority); + SetThreadPriorityBoost(curThread, true); + + for (uint32_t i = 0; i < c_NumTestLoops; i++) + { + uint64_t startTime = 0; + uint64_t endTime = 0; + uint32_t tscTime = 0; + uint64_t deltaTime = 0; + + m_senderReady = true; + while (!m_receiverReady); + m_senderDone = false; + startTime = __rdtscp(&tscTime); + endTime = __rdtscp(&tscTime); + while ((endTime - startTime) < c_SendDelay) // need to let receiver actually suspend before doing the release + { + endTime = __rdtscp(&tscTime); + } + m_calcedDelay = endTime - startTime; + m_waitAddress++; + startTime = __rdtscp(&tscTime); + WakeByAddressSingle(&m_waitAddress); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_releaseTimings[i] = deltaTime; + + while (!m_receiverDone) {} + m_senderReady = false; + m_senderDone = true; + } +} + +void PerfRun::ReceiveWaitAddressFunction(TestType /*whichTest*/, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriority(curThread, priority); + SetThreadPriorityBoost(curThread, true); + + for (uint32_t loopCount = 0; loopCount < c_NumTestLoops; loopCount++) + { + m_receiverReady = true; + while (!m_senderReady); + uint64_t startTime = 0; + uint64_t endTime = 0; + uint64_t deltaTime = 0; + uint32_t tscTime = 0; + uint64_t currentAddressValue = m_waitAddress; + startTime = __rdtscp(&tscTime); + WaitOnAddress(&m_waitAddress, ¤tAddressValue, 8, INFINITE); + endTime = __rdtscp(&tscTime); + m_receiverReady = false; + m_receiverDone = true; + while (!m_senderDone) {} + deltaTime = endTime - startTime; + m_memoryRaceTimings[loopCount] = (deltaTime < m_calcedDelay) ? 0 : deltaTime - m_calcedDelay; + m_memoryRaceTimingsRaw[loopCount] = deltaTime; + m_memoryRaceTimingsCalcedDelta[loopCount] = m_calcedDelay; + m_receiverDone = false; + } +} + +void PerfRun::SendCVFunction(TestType whichTest, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriority(curThread, priority); + SetThreadPriorityBoost(curThread, true); + + KernelFuncs[whichTest].second(); + for (uint32_t i = 0; i < c_NumTestLoops; i++) + { + uint64_t startTime = 0; + uint64_t endTime = 0; + uint32_t tscTime = 0; + uint64_t deltaTime = 0; + + m_senderReady = true; + while (!m_receiverReady); + KernelFuncs[whichTest].first(); + startTime = __rdtscp(&tscTime); + endTime = __rdtscp(&tscTime); + while ((endTime - startTime) < c_SendDelay) // need to let receiver actually suspend before doing the release + { + endTime = __rdtscp(&tscTime); + } + m_calcedDelay = endTime - startTime; + startTime = __rdtscp(&tscTime); + WakeConditionVariable(&m_conditionVariable); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_releaseTimings[i] = deltaTime; + + while (!m_receiverDone) {} + m_senderReady = false; + m_senderDone = true; + + KernelFuncs[whichTest].second(); + m_senderDone = false; + } + KernelFuncs[whichTest].first(); +} + +void PerfRun::ReceiveCVFunction(TestType whichTest, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriority(curThread, priority); + SetThreadPriorityBoost(curThread, true); + + for (uint32_t loopCount = 0; loopCount < c_NumTestLoops; loopCount++) + { + m_receiverReady = true; + while (!m_senderReady); + uint64_t startTime = 0; + uint64_t endTime = 0; + uint64_t deltaTime = 0; + uint32_t tscTime = 0; + startTime = __rdtscp(&tscTime); + KernelFuncs[whichTest].second(); + if (whichTest == PERFORM_CONDITION_CS) + SleepConditionVariableCS(&m_conditionVariable, &m_critSection, INFINITE); + else + SleepConditionVariableSRW(&m_conditionVariable, &m_srw, INFINITE, !CONDITION_VARIABLE_LOCKMODE_SHARED); + endTime = __rdtscp(&tscTime); + m_receiverReady = false; + m_receiverDone = true; + while (!m_senderDone) {} + deltaTime = endTime - startTime; + m_memoryRaceTimings[loopCount] = (deltaTime < m_calcedDelay) ? 0 : deltaTime - m_calcedDelay; + m_memoryRaceTimingsRaw[loopCount] = deltaTime; + m_memoryRaceTimingsCalcedDelta[loopCount] = m_calcedDelay; + m_receiverDone = false; + KernelFuncs[whichTest].first(); + } +} + +////////////////////////////////////////////////////////////////////////// +// +// +// +// The no contention functions +// +// +////////////////////////////////////////////////////////////////////////// + +void PerfRun::ReceiveKernelFunctionNoContention(TestType whichTest, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriorityBoost(curThread, true); + SetThreadPriority(curThread, priority); + + for (uint32_t loopCount = 0; loopCount < c_NumTestLoops; loopCount++) + { + uint64_t startTime = 0; + uint64_t endTime = 0; + uint64_t deltaTime = 0; + uint32_t tscTime = 0; + startTime = __rdtscp(&tscTime); + KernelFuncs[whichTest].second(); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_memoryRaceTimings[loopCount] = deltaTime; + startTime = __rdtscp(&tscTime); + KernelFuncs[whichTest].first(); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_releaseTimings[loopCount] = deltaTime; + } +} + +void PerfRun::ReceiveWaitAddressFunctionNoContention(TestType /*whichTest*/, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriority(curThread, priority); + SetThreadPriorityBoost(curThread, true); + + for (uint32_t loopCount = 0; loopCount < c_NumTestLoops; loopCount++) + { + uint64_t startTime = 0; + uint64_t endTime = 0; + uint64_t deltaTime = 0; + uint32_t tscTime = 0; + uint64_t currentAddressValue = m_waitAddress + 1; + startTime = __rdtscp(&tscTime); + WaitOnAddress(&m_waitAddress, ¤tAddressValue, 8, INFINITE); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_memoryRaceTimings[loopCount] = deltaTime; + startTime = __rdtscp(&tscTime); + WakeByAddressSingle(&m_waitAddress); + endTime = __rdtscp(&tscTime); + deltaTime = endTime - startTime; + m_releaseTimings[loopCount] = deltaTime; + } +} + +void PerfRun::ReceiveCVFunctionNoContention(TestType /*whichTest*/, uint32_t core, int32_t priority) +{ + HANDLE curThread = GetCurrentThread(); + + while (!m_startTestRun); + SetThreadAffinityMask(curThread, 1ULL << core); + SetThreadPriority(curThread, priority); + SetThreadPriorityBoost(curThread, true); + + // These tests don't really make sense. Condition variables need another thread to make the condition true + // If the condition was previously true then the thread would never sleep on the condition variable. + // This is due to the locking wrapper used by the condition variable which should be locked before checking the state of the condition + for (uint32_t loopCount = 0; loopCount < c_NumTestLoops; loopCount++) + { + m_releaseTimings[loopCount] = 0; + } +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/PerfRun.h b/XDKSamples/Tools/OSPrimitiveTool/PerfRun.h new file mode 100644 index 0000000000000000000000000000000000000000..1cbcfa36b42601b4490fdd705e48217e5a1e42b9 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/PerfRun.h @@ -0,0 +1,126 @@ +//-------------------------------------------------------------------------------------- +// PerfRun.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ATG +{ + namespace DebugLog + { + class FileLogger; + } +} + +class PerfRun +{ +public: + enum TestType + { + PERFORM_SEMAPHORE, + PERFORM_EVENT, + PERFORM_MUTEX, + PERFORM_SRW, + PERFORM_CRITICAL_SECTION, + PERFORM_WAIT_ADDRESS, + PERFORM_CONDITION_CS, + PERFORM_CONDITION_SRW, + NumTestTypeDefined, + + FirstTestTypeExecuted = PERFORM_SEMAPHORE, + LastTestTypeExecuted = PERFORM_CONDITION_SRW, + + FirstTestTypeDefined = PERFORM_SEMAPHORE, + LastTestTypeDefined = PERFORM_CONDITION_SRW, + }; + static std::wstring ConvertTestTypeToString(TestType testType) + { + switch (testType) + { + case PERFORM_SEMAPHORE: + return L"Semaphore"; + case PERFORM_EVENT: + return L"Event"; + case PERFORM_SRW: + return L"SRW"; + case PERFORM_MUTEX: + return L"Mutex"; + case PERFORM_CRITICAL_SECTION: + return L"Critical Section"; + case PERFORM_WAIT_ADDRESS: + return L"WaitOnAddress"; + case PERFORM_CONDITION_CS: + return L"Condition critical section"; + case PERFORM_CONDITION_SRW: + return L"Condition SRW"; + } + return L"Unknown"; + } + static const uint32_t c_NumTestLoops = 1000; + static const uint32_t c_SendDelay = 1000000; + static const uint32_t s_MaxCore = 7; + +private: + std::thread *m_senderThread; + std::thread *m_receiverThread; + std::vector m_workerThreads; + std::atomic m_startTestRun; + std::atomic m_senderReady; + std::atomic m_receiverReady; + std::atomic m_senderDone; + std::atomic m_receiverDone; + bool m_workerShutdown; + std::atomic m_calcedDelay; + uint64_t m_waitAddress; + + uint64_t m_memoryRaceTimings[c_NumTestLoops]; + uint64_t m_memoryRaceTimingsRaw[c_NumTestLoops]; + uint64_t m_memoryRaceTimingsCalcedDelta[c_NumTestLoops]; + uint64_t m_releaseTimings[c_NumTestLoops]; + + ATG::DebugLog::FileLogger *m_acquireLogfile; + ATG::DebugLog::FileLogger *m_releaseLogFile; + + HANDLE m_semaphore; + HANDLE m_event; + HANDLE m_mutex; + SRWLOCK m_srw; + CRITICAL_SECTION m_critSection; + CONDITION_VARIABLE m_conditionVariable; + + typedef std::function KernelFuncObject; + typedef std::pair KernelFuncPair; + KernelFuncPair KernelFuncs[NumTestTypeDefined]; + + void WorkerThread(uint32_t core, int32_t priority, bool suspend); + void SendKernelFunction(TestType whichTest, uint32_t core, int32_t priority); + void ReceiveKernelFunction(TestType whichTest, uint32_t core, int32_t priority); + + void SendWaitAddressFunction(TestType whichTest, uint32_t core, int32_t priority); + void ReceiveWaitAddressFunction(TestType whichTest, uint32_t core, int32_t priority); + + void SendCVFunction(TestType whichTest, uint32_t core, int32_t priority); + void ReceiveCVFunction(TestType whichTest, uint32_t core, int32_t priority); + + void ReceiveKernelFunctionNoContention(TestType whichTest, uint32_t core, int32_t priority); + + void ReceiveWaitAddressFunctionNoContention(TestType whichTest, uint32_t core, int32_t priority); + void ReceiveCVFunctionNoContention(TestType whichTest, uint32_t core, int32_t priority); + + void OpenLogFiles(bool noContention); + +public: + PerfRun(); + virtual ~PerfRun(); + + virtual void RunTests(uint32_t senderCore, uint32_t receiverCore, TestType whichTest, bool noContention, uint32_t idleWorkers); +}; diff --git a/XDKSamples/Tools/OSPrimitiveTool/Readme.docx b/XDKSamples/Tools/OSPrimitiveTool/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..73d465933464216615b1db319ac2c486bd53b118 Binary files /dev/null and b/XDKSamples/Tools/OSPrimitiveTool/Readme.docx differ diff --git a/XDKSamples/Tools/OSPrimitiveTool/SharedOSPrimitiveTool.cpp b/XDKSamples/Tools/OSPrimitiveTool/SharedOSPrimitiveTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ce46fcc9a7a61d8649debac4dd300d2dd7764fd --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/SharedOSPrimitiveTool.cpp @@ -0,0 +1,199 @@ +//-------------------------------------------------------------------------------------- +// SharedOSPrimitiveTool.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SharedOSPrimitiveTool.h" +#include "PerfRun.h" +#include "Logging/FileLogger.h" + +#include "XboxSpecificFiles/OSPrimitiveToolXbox.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +void PerformTests(SharedSample *data) +{ + Sleep(1000); // Wait a bit before starting the test run. 1 second is ample time for the render side to quiet down. + PerfRun baseRun; + if (data->m_noContention) + { + data->m_whatRunFinished = UINT32_MAX; + for (uint32_t testRun = PerfRun::TestType::FirstTestTypeExecuted; testRun < PerfRun::TestType::LastTestTypeExecuted; testRun++) + { + for (uint32_t i = 0; i < PerfRun::s_MaxCore; i++) + { + baseRun.RunTests(i, i, static_cast (testRun), data->m_noContention.load(), data->m_idleWorkers.load()); + } + data->m_whatRunFinished = testRun; + } + } + else + { + data->m_whatRunFinished = UINT32_MAX; + for (uint32_t testRun = PerfRun::TestType::FirstTestTypeExecuted; testRun < PerfRun::TestType::LastTestTypeExecuted; testRun++) + { + for (uint32_t i = 0; i < PerfRun::s_MaxCore; i++) + { + for (uint32_t j = 1; j < PerfRun::s_MaxCore; j++) + { + baseRun.RunTests(i, (i + j) % PerfRun::s_MaxCore, static_cast (testRun), data->m_noContention.load(), data->m_idleWorkers.load()); + } + } + data->m_whatRunFinished = testRun; + } + } + data->m_finishedTestRun = true; +} + +SharedSample::SharedSample(Sample* sample) : + m_sample(sample) + , m_cmdLineError(false) + , m_shutdownThread(false) + , m_finishedTestRun(false) + , m_noContention(false) + , m_idleWorkers(0) + , m_whatRunFinished(UINT32_MAX) +{ +} + +SharedSample::~SharedSample() +{ + m_shutdownThread = true; + m_workerThread->join(); + delete m_workerThread; +} + +void SharedSample::Update(DX::StepTimer const& /*timer*/) +{ + if (m_sample->m_timer.GetFrameCount() == 3) // let the system stabilize before actually running sample code. + { // Protection against issues with systems that initialize on D3D creation which can happen on the first frame. + m_noContention = false; + m_whatRunFinished = UINT32_MAX; + m_workerThread = new std::thread(PerformTests, this); + } + if (m_finishedTestRun) + { + if (m_noContention == false) + { + m_workerThread->join(); + delete m_workerThread; + m_noContention = true; + m_finishedTestRun = false; + m_workerThread = new std::thread(PerformTests, this); + } + } +} + +void SharedSample::Render() +{ + RECT safeRect = SimpleMath::Viewport::ComputeTitleSafeArea(1920, 1080); + + XMFLOAT2 pos(float(safeRect.left), float(safeRect.top)); + + m_sample->m_spriteBatch->Begin(); + + m_sample->m_spriteBatch->Draw(m_sample->m_background.Get(), m_sample->m_deviceResources->GetOutputSize()); + + if (m_sample->m_timer.GetFrameCount() > 3) + { + std::wstring outputString; + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + { + wchar_t buf[64] = {}; + swprintf(buf, 64, L" Frequency:%llu ", freq.QuadPart); + outputString += buf; + } + m_sample->m_font->DrawString(m_sample->m_spriteBatch.get(), outputString.c_str(), pos); + pos.y += 35; + + uint32_t numDots = (m_sample->m_timer.GetFrameCount() % 10) + 1; + if (m_cmdLineError) + { + outputString = L"Error Parsing Command Line"; + } + else if (m_finishedTestRun) + { + outputString = L"Finished Test Run"; + } + else + { + outputString = L"Doing "; + if (m_whatRunFinished == UINT32_MAX) + outputString += PerfRun::ConvertTestTypeToString(PerfRun::FirstTestTypeDefined); + else + outputString += PerfRun::ConvertTestTypeToString(static_cast (m_whatRunFinished + 1)); + if (m_noContention) + outputString += L" no contention"; + else + outputString += L" contention"; + } + + for (uint32_t i = 0; i < numDots; i++) + { + outputString += L"."; + } + m_sample->m_font->DrawString(m_sample->m_spriteBatch.get(), outputString.c_str(), pos); + } + + m_sample->m_spriteBatch->End(); +} + +std::vector SharedSample::BreakCommandLine(const wchar_t *commandLineParams) +{ + const wchar_t *cur, *start; + std::vector toret; + + start = commandLineParams; + cur = start; + while (*cur != 0) + { + while (!isspace(*cur) && (*cur != 0)) + ++cur; + toret.push_back(std::wstring(start, cur - start)); + while (isspace(*cur) && (*cur != 0)) + ++cur; + start = cur; + } + if (start != cur) + { + toret.push_back(std::wstring(start, cur - start)); + } + return toret; +} + +void SharedSample::ParseCommandLine(const wchar_t *commandlineParams) +{ + std::vector cmdLine; + + m_noContention = false; + cmdLine = BreakCommandLine(commandlineParams); + + std::vector::iterator iter, endIter; + std::vector::iterator firstParam, secondParam; + endIter = cmdLine.end(); + for (iter = cmdLine.begin(); (iter != endIter) && (!m_cmdLineError); ++iter) + { + if (*iter == L"idleWorkers") + { + firstParam = iter; + ++firstParam; + if (firstParam == endIter) + { + m_cmdLineError = true; + continue; + } + m_idleWorkers = std::stoi(*firstParam); + ++iter; + continue; + } + else + { + m_cmdLineError = true; + } + } +} \ No newline at end of file diff --git a/XDKSamples/Tools/OSPrimitiveTool/SharedOSPrimitiveTool.h b/XDKSamples/Tools/OSPrimitiveTool/SharedOSPrimitiveTool.h new file mode 100644 index 0000000000000000000000000000000000000000..26925fd9389ecc691172158a2e23dff3341bfd28 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/SharedOSPrimitiveTool.h @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------------------- +// ShardOSPrimitiveTool.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include "StepTimer.h" +#include +#include +#include + +class Sample; + +class SharedSample +{ + friend void PerformTests(SharedSample *data); + +private: + Sample *m_sample; // The lifetime of this class is entirely within the lifetime of this Sample + + std::vector BreakCommandLine(const wchar_t *commandLineParams); + +private: + bool m_cmdLineError; + + std::atomic m_shutdownThread; + std::atomic m_finishedTestRun; + std::atomic m_noContention; + std::atomic m_idleWorkers; + std::atomic m_whatRunFinished; + std::thread *m_workerThread; + +public: + SharedSample(Sample* sample); + ~SharedSample(); + + void Update(DX::StepTimer const& timer); + void Render(); + + void ParseCommandLine(const wchar_t *commandlineParams); +}; diff --git a/XDKSamples/Tools/OSPrimitiveTool/StepTimer.h b/XDKSamples/Tools/OSPrimitiveTool/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/Telemetry.h b/XDKSamples/Tools/OSPrimitiveTool/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/DeviceResourcesXbox.cpp b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/DeviceResourcesXbox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f49b3768da45eef146f04430973ea5ef7c4a6bc8 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/DeviceResourcesXbox.cpp @@ -0,0 +1,237 @@ +// +// DeviceResourcesXbox.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResourcesXbox.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, bool fastSemantics) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{ 0, 0, 1920, 1080 }, + m_fastSemantics(fastSemantics) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + if (m_fastSemantics) + { + creationFlags |= D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = { nullptr }; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_renderTarget.Reset(); + m_depthStencil.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + m_renderTarget.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + m_depthStencil.ReleaseAndGetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + m_depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ + if (m_fastSemantics) + { + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); + + m_d3dDevice->PlaceSwapChainView(m_renderTarget.Get(), m_d3dRenderTargetView.Get()); + + m_d3dContext->InsertWaitOnPresent(0, m_renderTarget.Get()); + } +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present(UINT decompressFlags) +{ + if (m_fastSemantics && decompressFlags) + { + m_d3dContext->DecompressResource( + m_renderTarget.Get(), 0, nullptr, + m_renderTarget.Get(), 0, nullptr, + m_backBufferFormat, decompressFlags); + } + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/DeviceResourcesXbox.h b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/DeviceResourcesXbox.h new file mode 100644 index 0000000000000000000000000000000000000000..e816203a63b3eee0036e1265e2307023fbf5a0d9 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/DeviceResourcesXbox.h @@ -0,0 +1,66 @@ +// +// DeviceResourcesXbox.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + bool fastSemantics = false); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(UINT decompressFlags = D3D11X_DECOMPRESS_PROPAGATE_COLOR_CLEAR); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } + ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_renderTarget; + Microsoft::WRL::ComPtr m_depthStencil; + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + + bool m_fastSemantics; + }; +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/MainXbox.cpp b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/MainXbox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..278527fc5f7750a70ffc7da2d86eb4cda512eacf --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/MainXbox.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// MainXbox.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "OSPrimitiveToolXbox.h" + +#include + +#include "../Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH + 1] = {}; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + if (args->Kind == ActivationKind::Launch) + { + LaunchActivatedEventArgs ^launchArgs = (LaunchActivatedEventArgs ^)args; + Platform::String ^commandlineParams = launchArgs->Arguments; + m_sample->ParseCommandLine(commandlineParams); + /* parse commandlineParams .... */ + } + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/OSPrimitiveToolXbox.cpp b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/OSPrimitiveToolXbox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5aa4a88f1f71a3d7d4dbb9f4410ba3bcd12cca73 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/OSPrimitiveToolXbox.cpp @@ -0,0 +1,161 @@ +//-------------------------------------------------------------------------------------- +// OSPrimitiveToolXbox.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "OSPrimitiveToolXbox.h" + +#include "ATGColors.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + m_sharedSample = std::make_unique(this); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + m_sharedSample->Update(timer); + elapsedTime; + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + m_sharedSample->Render(); + + PIXEndEvent(context); + + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_spriteBatch = std::make_unique(context); + m_font = std::make_unique(device, L"SegoeUI_18.spritefont"); + DX::ThrowIfFailed(CreateDDSTextureFromFile(device, L"ATGSampleBackground.DDS", nullptr, m_background.ReleaseAndGetAddressOf())); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ +} +#pragma endregion diff --git a/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/OSPrimitiveToolXbox.h b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/OSPrimitiveToolXbox.h new file mode 100644 index 0000000000000000000000000000000000000000..3efbb58bec2e715d7adb0cab670e50d78f0ab735 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/OSPrimitiveToolXbox.h @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// OSPrimitiveToolXbox.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResourcesXbox.h" +#include "../StepTimer.h" +#include "../SharedOSPrimitiveTool.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ + friend class SharedSample; + +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + void ParseCommandLine(Platform::String ^commandlineParams) { m_sharedSample->ParseCommandLine(commandlineParams->Data()); } + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + Microsoft::WRL::ComPtr m_background; + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_spriteBatch; + std::unique_ptr m_font; + + std::unique_ptr m_sharedSample; +}; diff --git a/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/Package.appxmanifest b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..398e95f9215bc1cfd520ec26ac24682ce73babf8 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/XBoxSpecificFiles/Package.appxmanifest @@ -0,0 +1,52 @@ + + + + + + + OSPrimitiveTestXbox + Xbox Advanced Technology Group + Assets\StoreLogo.png + OSPrimitiveTestXbox + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + variable + + + + + + + + + diff --git a/XDKSamples/Tools/OSPrimitiveTool/pch.cpp b/XDKSamples/Tools/OSPrimitiveTool/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Tools/OSPrimitiveTool/pch.h b/XDKSamples/Tools/OSPrimitiveTool/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..68a77ae2e76072e6327bc5789e7e8f5940ab1dc2 --- /dev/null +++ b/XDKSamples/Tools/OSPrimitiveTool/pch.h @@ -0,0 +1,74 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include +#if _XDK_VER < 0x295A0401 /* XDK Edition 151100 */ +#error This sample requires the November 2015 XDK or later +#endif +#include +#include +#include + +#ifndef _CONSOLE +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifndef _CONSOLE +#include "GamePad.h" +#include "Keyboard.h" +#include "Mouse.h" +#include "DDSTextureLoader.h" +#include "GraphicsMemory.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "SimpleMath.h" +#endif + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} diff --git a/XDKSamples/Tools/RasterFontGen/GGO_Glyph.cpp b/XDKSamples/Tools/RasterFontGen/GGO_Glyph.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3cef0dfa7bcd5ebb15f9aee784af4d7f5d426e0 --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/GGO_Glyph.cpp @@ -0,0 +1,98 @@ +//-------------------------------------------------------------------------------------- +// GGO_Glyph.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GGO_Glyph.h" + +using namespace ATG; + +ATG::GGO_Glyph::GGO_Glyph() + : m_ggoFormat(0) + , m_character(0) + , m_glyphMetrics{} + , m_bufferSize(0) +{ +} + +ATG::GGO_Glyph::GGO_Glyph(HDC hdc, wchar_t wc, uint32_t ggoFormat) + : m_ggoFormat(ggoFormat) + , m_character(wc) + , m_glyphMetrics{} + , m_bufferSize(0) +{ + + switch (m_ggoFormat) + { + case GGO_BITMAP: + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + break; + + default: + throw DX::exception_fmt<64>("Unsupported GGO format (%i). Must use a bitmap format see docs for GetGlyphOutline", m_ggoFormat); + } + + MAT2 matrix = {}; + matrix.eM11.value = 1; + matrix.eM12.value = 0; + matrix.eM21.value = 0; + matrix.eM22.value = 1; + + uint32_t result = GetGlyphOutline( + hdc, + wc, + m_ggoFormat, + &m_glyphMetrics, + 0, + nullptr, + &matrix); + + if (result != GDI_ERROR) + { + m_bufferSize = result; + m_spritePixels = std::make_unique(result); + + // GGO_BITMAP: + // Returns the glyph bitmap.When the function returns, the buffer pointed to by lpBuffer + // contains a 1 - bit - per - pixel bitmap whose rows start on double-word boundaries. + + result = GetGlyphOutline( + hdc, + wc, + m_ggoFormat, + &m_glyphMetrics, + result, + m_spritePixels.get(), + &matrix); + } + + if (result == GDI_ERROR) + { + throw DX::exception_fmt<128>("Not able to get the glyph bitmap for character code: %i", wc); + } +} + +ATG::GGO_Glyph::GGO_Glyph(GGO_Glyph && moveFrom) + : m_ggoFormat(moveFrom.m_ggoFormat) + , m_character(moveFrom.m_character) + , m_bufferSize(moveFrom.m_bufferSize) +{ + memcpy(&m_glyphMetrics, &moveFrom.m_glyphMetrics, sizeof(GLYPHMETRICS)); + m_spritePixels = std::move(moveFrom.m_spritePixels); +} + +GGO_Glyph & ATG::GGO_Glyph::operator=(GGO_Glyph && moveFrom) +{ + m_ggoFormat = moveFrom.m_ggoFormat; + m_character = moveFrom.m_character; + m_bufferSize = moveFrom.m_bufferSize; + memcpy(&m_glyphMetrics, &moveFrom.m_glyphMetrics, sizeof(GLYPHMETRICS)); + m_spritePixels = std::move(moveFrom.m_spritePixels); + + return *this; +} diff --git a/XDKSamples/Tools/RasterFontGen/GGO_Glyph.h b/XDKSamples/Tools/RasterFontGen/GGO_Glyph.h new file mode 100644 index 0000000000000000000000000000000000000000..927156776cf8ad6d5a32fd5e167468fddcfacb81 --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/GGO_Glyph.h @@ -0,0 +1,142 @@ +//-------------------------------------------------------------------------------------- +// GGO_Glyph.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +namespace ATG +{ + // -------------------------------------------------------------------------------- + // GGO_Glyph + // a glyph helper class based on GetGlyphOutline + // -------------------------------------------------------------------------------- + class GGO_Glyph + { + public: + GGO_Glyph(); + + GGO_Glyph(HDC hdc, wchar_t wc, uint32_t ggoFormat); + + + GGO_Glyph(const GGO_Glyph&) = delete; + GGO_Glyph &operator=(const GGO_Glyph&) = delete; + + GGO_Glyph(GGO_Glyph &&moveFrom); + + GGO_Glyph &operator=(GGO_Glyph &&moveFrom); + + + uint32_t GetGGOFormat() const + { + return m_ggoFormat; + } + + uint32_t GetCharacterCode() const + { + return m_character; + } + + const GLYPHMETRICS &GetMetrics() const + { + return m_glyphMetrics; + } + + uint8_t *GetPixels() const + { + return m_spritePixels.get(); + } + + unsigned GetBufferSize() const + { + return m_bufferSize; + } + + template + void ForEachPixel(ACTION_T fn) const + { + if (m_ggoFormat == GGO_BITMAP) + { + ForEach_GGO_Pixel(fn); + } + else + { + ForEach_GGO_GRAY_N_Pixel(fn); + } + } + + private: + + template + void ForEach_GGO_Pixel(ACTION_T fn) const + { + const unsigned rows = m_glyphMetrics.gmBlackBoxY; + const unsigned cols = m_glyphMetrics.gmBlackBoxX; + const unsigned doubleWordsPerRow = GetStorageSize(cols); + const unsigned bytesPerRow = doubleWordsPerRow * 4; + + uint8_t *srcByte = m_spritePixels.get(); + if (srcByte == nullptr) + { + return; + } + + for (unsigned row = 0; row < rows; ++row) + { + unsigned col = 0; + for (unsigned b = 0; b < bytesPerRow; ++b) + { + for (int shift = 7; shift >= 0; --shift) + { + if (col >= cols) + break; + + uint8_t clr = (((srcByte[b]) >> shift) & 0x1) * 0xFF; + fn(col, row, clr); + ++col; + } + if (col >= cols) + break; + } + srcByte += bytesPerRow; + } + } + + template + void ForEach_GGO_GRAY_N_Pixel(ACTION_T fn) const + { + unsigned rows = m_glyphMetrics.gmBlackBoxY; + unsigned cols = m_glyphMetrics.gmBlackBoxX; + unsigned stride = m_bufferSize / rows; + + uint8_t *srcPixels = m_spritePixels.get(); + + if (srcPixels == nullptr) + { + return; + } + + for (unsigned i = 0; i < cols; ++i) + { + for (unsigned j = 0; j < rows; ++j) + { + uint8_t clr = srcPixels[i + j * stride]; + fn(i, j, clr); + } + } + } + + uint32_t m_ggoFormat; + uint32_t m_character; + GLYPHMETRICS m_glyphMetrics; + std::unique_ptr m_spritePixels; + unsigned m_bufferSize; + }; + +} // namespace ATG diff --git a/XDKSamples/Tools/RasterFontGen/RasterFontGen.sln b/XDKSamples/Tools/RasterFontGen/RasterFontGen.sln new file mode 100644 index 0000000000000000000000000000000000000000..5231a67c225d504af2f307d52c1b77969f7752d5 --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/RasterFontGen.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RasterFontGen", "RasterFontGen.vcxproj", "{83AF7426-8094-4AC7-B1A7-158305458C30}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {83AF7426-8094-4AC7-B1A7-158305458C30}.Debug|x64.ActiveCfg = Debug|x64 + {83AF7426-8094-4AC7-B1A7-158305458C30}.Debug|x64.Build.0 = Debug|x64 + {83AF7426-8094-4AC7-B1A7-158305458C30}.Debug|x86.ActiveCfg = Debug|x64 + {83AF7426-8094-4AC7-B1A7-158305458C30}.Release|x64.ActiveCfg = Release|x64 + {83AF7426-8094-4AC7-B1A7-158305458C30}.Release|x64.Build.0 = Release|x64 + {83AF7426-8094-4AC7-B1A7-158305458C30}.Release|x86.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Tools/RasterFontGen/RasterFontGen.vcxproj b/XDKSamples/Tools/RasterFontGen/RasterFontGen.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..e32f46e66576d6c75ea000e29eb80e201d27bf0d --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/RasterFontGen.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {83AF7426-8094-4AC7-B1A7-158305458C30} + Win32Proj + RasterFontGen + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + true + + + false + + + + Use + pch.h + ..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + Use + pch.h + ..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontGen/RasterFontGen.vcxproj.filters b/XDKSamples/Tools/RasterFontGen/RasterFontGen.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..d8f24d4aaeb9c28cfda45c969f24e315053fbc26 --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/RasterFontGen.vcxproj.filters @@ -0,0 +1,47 @@ + + + + + {c6391268-837a-4b32-b01f-28a0fcfde7d3} + + + + + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontGen/main.cpp b/XDKSamples/Tools/RasterFontGen/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d601cb64c58cc4c1462849bcb224be09b58e07b --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/main.cpp @@ -0,0 +1,827 @@ +//-------------------------------------------------------------------------------------- +// main.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "GGO_Glyph.h" +#include "FrontPanel\RasterFont.h" +#include "CommandLineHelpers.h" + +#include + +using namespace ATG; + +namespace +{ + enum OPTIONS : uint32_t + { + OPT_TYPEFACE = 1, + OPT_HEIGHT, + OPT_WEIGHT, + OPT_ITALIC, + OPT_UNDERLINE, + OPT_STRIKEOUT, + OPT_CHARSET, + OPT_QUALITY, + OPT_PITCH, + OPT_FAMILY, + OPT_GGO_DEPTH, + OPT_CHARACTER_REGION, + OPT_OUTPUT_FILENAME, + OPT_DEFAULT_GLYPH, + OPT_OVERWRITE, + OPT_MAX + }; + + static_assert(OPT_MAX <= 64, "Options must fit into a uint64_t bitfield"); + + + const SValue g_Options[] = + { + { L"tf", OPT_TYPEFACE }, + { L"h", OPT_HEIGHT }, + { L"w", OPT_WEIGHT }, + { L"it", OPT_ITALIC }, + { L"ul", OPT_UNDERLINE }, + { L"so", OPT_STRIKEOUT }, + { L"cs", OPT_CHARSET }, + { L"q", OPT_QUALITY }, + { L"p", OPT_PITCH }, + { L"fa", OPT_FAMILY }, + { L"d", OPT_GGO_DEPTH }, + { L"cr", OPT_CHARACTER_REGION }, + { L"of", OPT_OUTPUT_FILENAME }, + { L"ow", OPT_OVERWRITE }, + { L"dg", OPT_DEFAULT_GLYPH }, + }; + +#define DEF_WEIGHT(wght) { L#wght, FW_ ## wght } + const SValue g_Weights[] = + { + DEF_WEIGHT(DONTCARE), + DEF_WEIGHT(THIN), + DEF_WEIGHT(EXTRALIGHT), + DEF_WEIGHT(LIGHT), + DEF_WEIGHT(NORMAL), + DEF_WEIGHT(MEDIUM), + DEF_WEIGHT(SEMIBOLD), + DEF_WEIGHT(BOLD), + DEF_WEIGHT(EXTRABOLD), + DEF_WEIGHT(HEAVY), + DEF_WEIGHT(ULTRALIGHT), + DEF_WEIGHT(REGULAR), + DEF_WEIGHT(DEMIBOLD), + DEF_WEIGHT(ULTRABOLD), + DEF_WEIGHT(BLACK) + }; +#undef DEF_WEIGHT + +#define DEF_CHARSET(chrst) { L#chrst, chrst ## _CHARSET } + const SValue g_Charsets[] = + { + DEF_CHARSET(ANSI), + DEF_CHARSET(DEFAULT), + DEF_CHARSET(SYMBOL), + DEF_CHARSET(SHIFTJIS), + DEF_CHARSET(HANGEUL), + DEF_CHARSET(HANGUL), + DEF_CHARSET(GB2312), + DEF_CHARSET(CHINESEBIG5), + DEF_CHARSET(OEM), + DEF_CHARSET(JOHAB), + DEF_CHARSET(HEBREW), + DEF_CHARSET(ARABIC), + DEF_CHARSET(GREEK), + DEF_CHARSET(TURKISH), + DEF_CHARSET(VIETNAMESE), + DEF_CHARSET(THAI), + DEF_CHARSET(EASTEUROPE), + DEF_CHARSET(RUSSIAN), + DEF_CHARSET(MAC), + DEF_CHARSET(BALTIC) + }; +#undef DEF_CHARSET + +#define DEF_QUALITY(qlty) { L#qlty, qlty ## _QUALITY } + const SValue g_Qualities[] = + { + DEF_QUALITY(ANTIALIASED), + DEF_QUALITY(CLEARTYPE), + DEF_QUALITY(DEFAULT), + DEF_QUALITY(DRAFT), + DEF_QUALITY(NONANTIALIASED), + DEF_QUALITY(PROOF) + }; +#undef DEF_QUALITY + +#define DEF_PITCH(ptch) { L#ptch, ptch ## _PITCH} + const SValue g_Pitches[] = + { + DEF_PITCH(DEFAULT), + DEF_PITCH(FIXED), + DEF_PITCH(VARIABLE) + }; +#undef DEF_PITCH + +#define DEF_FAMILY(fam) { L#fam, FF_ ## fam } + const SValue g_Families[] = + { + DEF_FAMILY(DECORATIVE), + DEF_FAMILY(DONTCARE), + DEF_FAMILY(MODERN), + DEF_FAMILY(ROMAN), + DEF_FAMILY(SCRIPT), + DEF_FAMILY(SWISS) + }; +#undef DEF_FAMILY + +#define DEF_GGO_DEPTH(ggo) { L#ggo, GGO_ ## ggo ## _BITMAP } + const SValue g_GGO_Depths[] = + { + { L"1BPP", GGO_BITMAP }, + DEF_GGO_DEPTH(GRAY2), + DEF_GGO_DEPTH(GRAY4), + DEF_GGO_DEPTH(GRAY8) + }; +#undef DEF_GGO_DEPTH + + bool ParseDefaultGlyph(const wchar_t *charCode, wchar_t &defaultGlyph, std::vector ®ions) + { + const wchar_t *hexCode = charCode; + + // Match and consume the hex prefix '0x' + if (_wcsnicmp(L"0x", hexCode, 2) != 0) + { + wprintf(L"Expected a hexidecimal character code specification\n"); + return false; + } + hexCode += 2; + + unsigned code = 0; + // Scan the hex value + if (swscanf_s(hexCode, L"%lx", &code) != 1) + { + wprintf(L"Expected a hexidecimal value following the prefix ('0x')\n"); + return false; + } + hexCode = ConsumeDigits(hexCode); + + if (code > 0xFFFF) + { + wprintf(L"The hexidecimal value of the character code specification is too large (0x%X)\n", code); + return false; + } + + if (*hexCode) + { + wprintf(L"Unexpected characters following the character code specification (%ls).\n", hexCode); + return false; + } + + defaultGlyph = code; + WCRANGE range = { wchar_t(code), 1 }; + regions.push_back(range); + return true; + } + + void PrintLogo() + { + wprintf(L"Microsoft (R) Raster Font Generator for for Xbox One\n"); + wprintf(L"Copyright (C) Microsoft Corp. All rights reserved.\n"); +#ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); +#endif + wprintf(L"\n"); + } + + void PrintUsage() + { + PrintLogo(); + + wprintf(L"Usage: rasterfontgen \n\n"); + wprintf(L" -tf Name of the font typeface\n"); + wprintf(L" -h [REQUIRED] Height of the font's character cell in logical units\n"); + wprintf(L" -w Font weight\n"); + wprintf(L" -it Specifies an italic font\n"); + wprintf(L" -ul Specifies an underlined font\n"); + wprintf(L" -so Specifies a strikeout font\n"); + wprintf(L" -cs The character set\n"); + wprintf(L" -q The output quality\n"); + wprintf(L" -p The pitch of the font\n"); + wprintf(L" -fa The family of the font\n"); + wprintf(L" -d The GetGlyphOutline (GGO) pixel depth\n"); + wprintf(L" -cr: Character region. Specifies a range of unicode code points to include in the font.\n"); + wprintf(L" Examples: -cr:a-z -cr:0x1200-0x1250 -cr:0x1234\n"); + wprintf(L" -of [REQUIRED] Name of the output file\n"); + wprintf(L" -ow Overwrite the output file if it already exists\n"); + wprintf(L" -dg Specifies the default glyph to use when the font does not support a particular character code\n"); + wprintf(L" Examples: -dg:0x1234\n"); + + const wchar_t wgts[] = L"\n : "; + wprintf(wgts); + PrintTable(_countof(wgts) - 2, g_Weights); + + const wchar_t chsts[] = L"\n : "; + wprintf(chsts); + PrintTable(_countof(chsts) - 2, g_Charsets); + + const wchar_t qlties[] = L"\n : "; + wprintf(qlties); + PrintTable(_countof(qlties) - 2, g_Qualities); + + const wchar_t ptchs[] = L"\n : "; + wprintf(ptchs); + PrintTable(_countof(ptchs) - 2, g_Pitches); + + const wchar_t fams[] = L"\n : "; + wprintf(fams); + PrintTable(_countof(fams) - 2, g_Families); + + const wchar_t dpths[] = L"\n : "; + wprintf(dpths); + PrintTable(_countof(dpths) - 2, g_GGO_Depths); + } + + void GetGlyphRanges(HDC hDC, std::vector &ranges) + { + std::unique_ptr glyphSetBytes; + GLYPHSET *glyphSet = nullptr; + { + auto size = GetFontUnicodeRanges(hDC, nullptr); + glyphSetBytes = std::make_unique(size); + + glyphSet = reinterpret_cast(glyphSetBytes.get()); + + if (!GetFontUnicodeRanges(hDC, glyphSet)) + { + throw std::exception("Unable to get unicode ranges for font."); + } + + for (unsigned r = 0; r < glyphSet->cRanges; ++r) + { + ranges.push_back(glyphSet->ranges[r]); + } + } + } + + + bool IsCodePointInRange(wchar_t codePoint, const WCRANGE &range) + { + wchar_t firstCharacter = range.wcLow; + wchar_t lastCharacter = firstCharacter + range.cGlyphs - 1; + + return (codePoint >= firstCharacter && codePoint <= lastCharacter); + } + + bool FilterKerningPair(const KERNINGPAIR &pair, const std::vector &ranges) + { + bool firstInRange = false; + bool secondInRange = false; + + for (unsigned r = 0; r < ranges.size(); ++r) + { + firstInRange = firstInRange || IsCodePointInRange(pair.wFirst, ranges[r]); + secondInRange = secondInRange || IsCodePointInRange(pair.wSecond, ranges[r]); + + if (firstInRange && secondInRange) + { + return true; + } + } + + return false; + } + + bool FilterCodePoint(wchar_t codePoint, const std::vector &ranges) + { + for(unsigned r = 0; r < ranges.size(); ++r) + { + if (IsCodePointInRange(codePoint, ranges[r])) + { + return true; + } + } + return false; + } + + void Create_GGO_Glyphs( + LOGFONT *logfont, + unsigned ggoDepth, + const std::vector &requestedRanges, + std::vector &kerningPairs, + std::vector &ggoGlyphs, + wchar_t requestedDefaultGlyph) + { + // Set up a memory device context for laying out the glyph sheet + HDC hDC = GetDC(nullptr); + HDC memDC = CreateCompatibleDC(hDC); + + HFONT font = CreateFontIndirect(logfont); + + if (!font) + { + throw std::exception("Could not create font."); + } + + SelectObject(memDC, font); + + wchar_t defaultGlyph = requestedDefaultGlyph; + + // Check to see if it is a TrueType font and early out if not + { + TEXTMETRIC metrics = {}; + if (!GetTextMetrics(memDC, &metrics)) + { + throw std::exception("Could not get text metrics."); + } + + bool isTrueType = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) == TMPF_TRUETYPE; + if (!isTrueType) + { + throw std::exception("Requested font is not a TrueType font"); + } + + if (requestedDefaultGlyph == '\0') + { + requestedDefaultGlyph = metrics.tmDefaultChar; + } + } + + // Get the supported Unicode ranges for the font + std::vector supportedRanges; + GetGlyphRanges(memDC, supportedRanges); + + // Get the kerning pairs for the font + { + unsigned numPairs = GetKerningPairs(memDC, 0, nullptr); + std::unique_ptr kerns = std::make_unique(numPairs); + + auto test = GetKerningPairs(memDC, numPairs, kerns.get()); + if (numPairs != test) + { + throw std::exception("Unable to get kerning pairs for the font."); + } + + for (unsigned i = 0; i < numPairs; ++i) + { + KERNINGPAIR &pair = kerns[i]; + if (requestedRanges.size() == 0) + { + if (FilterKerningPair(pair, supportedRanges)) + { + kerningPairs.push_back(pair); + } + } + else + { + if (FilterKerningPair(pair, requestedRanges) && FilterKerningPair(pair, supportedRanges)) + { + kerningPairs.push_back(pair); + } + } + } + } + + // Create the GGO_Glyphs for the font + { + std::set includedCodePoints; + includedCodePoints.insert(defaultGlyph); + if (requestedRanges.size() == 0) + { + for (int r = 0; r < supportedRanges.size(); ++r) + { + const WCRANGE &range = supportedRanges[r]; + wchar_t firstCharacter = range.wcLow; + wchar_t lastCharacter = range.wcLow + range.cGlyphs - 1; + + for (wchar_t wc = firstCharacter; wc <= lastCharacter; ++wc) + { + includedCodePoints.insert(wc); + } + } + } + else + { + for (int rr = 0; rr < requestedRanges.size(); ++rr) + { + const WCRANGE &range = requestedRanges[rr]; + wchar_t firstCharacter = range.wcLow; + wchar_t lastCharacter = range.wcLow + range.cGlyphs - 1; + + for (wchar_t wc = firstCharacter; wc <= lastCharacter; ++wc) + { + if (FilterCodePoint(wc, supportedRanges)) + { + includedCodePoints.insert(wc); + } + else + { + wprintf(L"The code point, 0x%04x, is not supported by the font and will not be included.\n", wc); + } + } + } + } + + for (auto itr = includedCodePoints.begin(); itr != includedCodePoints.end(); ++itr) + { + ggoGlyphs.emplace_back(memDC, *itr, ggoDepth); + } + } + + DeleteObject(font); + DeleteObject(memDC); + } + + size_t CreatePixelBuffer(const std::vector &ggoGlyphs, uint8_t *pixels, size_t pixelBufferSize) + { + + size_t pixelByteCount = 0; + // Allocate the buffer for the glyph pixels + { + for (int i = 0; i < ggoGlyphs.size(); ++i) + { + auto metrics = ggoGlyphs[i].GetMetrics(); + pixelByteCount += GetStorageSize(metrics.gmBlackBoxX * metrics.gmBlackBoxY); + } + + if (pixels == nullptr || pixelByteCount > pixelBufferSize) + { + return pixelByteCount; + } + + memset(pixels, 0, pixelBufferSize); + } + + // Copy the glyphs into the pixel buffer + { + uint8_t *pxls = pixels; + for (int i = 0; i < ggoGlyphs.size(); ++i) + { + unsigned pixelIdx = 0; + ggoGlyphs[i].ForEachPixel([&](unsigned col, unsigned row, uint8_t clr) { + unsigned shift = 7 - (pixelIdx % 8); + pxls[pixelIdx / 8] |= (!!clr) << shift; + pixelIdx++; + }); + + auto metrics = ggoGlyphs[i].GetMetrics(); + + pxls += GetStorageSize(metrics.gmBlackBoxX * metrics.gmBlackBoxY); + } + } + + return pixelByteCount; + } + + void ComputeAscentDescent( + const std::vector &ggoGlyphs, + unsigned &effectiveAscent, + unsigned &effectiveDescent) + { + effectiveAscent = 0; + effectiveDescent = 0; + + // Compute the effective ascent and effective descent based on the actual glyphs + { + for (int i = 0; i < ggoGlyphs.size(); ++i) + { + auto metrics = ggoGlyphs[i].GetMetrics(); + + int ascent = metrics.gmptGlyphOrigin.y; + if (ascent > 0) + { + // Positive vertical coordinate places the upper left corner of the glyph's + // "black box" above the glyph base-line. + effectiveAscent = std::max(effectiveAscent, unsigned(ascent)); + } + + // Compute the descent for the character as a signed vertical distance from the + // lower-left corner of the glyph's "black box" to the glyph base-line. + // A negative value indicates that nothing is drawn below the base-line. + int descent = metrics.gmBlackBoxY - metrics.gmptGlyphOrigin.y; + if (descent > 0) + { + effectiveDescent = std::max(effectiveDescent, unsigned(descent)); + } + } + + ++effectiveAscent; + } + } + +} // ANONYMOUS namespace + + + + + +int wmain(int argc, wchar_t *argv[]) +{ + // Parameters and defaults + const wchar_t *typeFace = nullptr; + unsigned fontHeight = 0; + unsigned fontWeight = FW_DONTCARE; + bool useItalic = false; + bool useUnderline = false; + bool useStrikeOut = false; + unsigned charset = DEFAULT_CHARSET; + unsigned quality = DEFAULT_QUALITY; + unsigned pitch = DEFAULT_PITCH; + unsigned family = FF_DONTCARE; + unsigned ggoDepth = GGO_BITMAP; + const wchar_t *outputFilename = nullptr; + bool overwriteOutputFile = false; + wchar_t defaultGlyph = '\0'; + std::vector regions; + + unsigned individualOptions = 0; + + // Parse the command line + for (int argIdx = 0; argIdx < argc; ++argIdx) + { + wchar_t *arg = argv[argIdx]; + + if (('-' == arg[0]) || ('/' == arg[0])) + { + arg++; + + wchar_t *value = nullptr; + for (value = arg; *value && (':' != *value); ++value); + if (*value) + *value++ = 0; + + unsigned option = 0; + if( !LookupByName(arg, g_Options, option) || (individualOptions & (1 << option))) + { + PrintUsage(); + return 1; + } + + if (option != OPT_CHARACTER_REGION) + { + individualOptions |= (1 << option); + } + + // Handle options with an additional value parameter + switch (option) + { + case OPT_TYPEFACE: + case OPT_HEIGHT: + case OPT_WEIGHT: + case OPT_CHARSET: + case OPT_QUALITY: + case OPT_PITCH: + case OPT_FAMILY: + case OPT_GGO_DEPTH: + case OPT_CHARACTER_REGION: + case OPT_OUTPUT_FILENAME: + case OPT_DEFAULT_GLYPH: + if (!*value) + { + if (argIdx + 1 >= argc) + { + PrintUsage(); + return 1; + } + + ++argIdx; + value = argv[argIdx]; + } + break; + } + + switch (option) + { + case OPT_TYPEFACE: + typeFace = value; + break; + + case OPT_HEIGHT: + if (swscanf_s(value, L"%lu", &fontHeight) != 1) + { + wprintf(L"Invalid value specified with -h (%ls)\n", value); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_WEIGHT: + if (!ParseTableValue(option, value, g_Weights, fontWeight)) + { + PrintUsage(); + return 1; + } + break; + + case OPT_ITALIC: + useItalic = true; + break; + + case OPT_UNDERLINE: + useUnderline = true; + break; + + case OPT_STRIKEOUT: + useStrikeOut = true; + break; + + case OPT_CHARSET: + if (!ParseTableValue(option, value, g_Charsets, charset)) + { + PrintUsage(); + return 1; + } + break; + + case OPT_QUALITY: + if (!ParseTableValue(option, value, g_Qualities, quality)) + { + PrintUsage(); + return 1; + } + break; + + case OPT_PITCH: + if (!ParseTableValue(option, value, g_Pitches, pitch)) + { + PrintUsage(); + return 1; + } + break; + + case OPT_FAMILY: + if (!ParseTableValue(option, value, g_Families, family)) + { + PrintUsage(); + return 1; + } + break; + + case OPT_GGO_DEPTH: + if (!ParseTableValue(option, value, g_GGO_Depths, ggoDepth)) + { + PrintUsage(); + return 1; + } + break; + + case OPT_CHARACTER_REGION: + if (!ParseCharacterRegion(value, regions)) + { + wprintf(L"Invalid character region value specified with -%ls: (%ls)\n", LookupByValue(OPT_CHARACTER_REGION, g_Options), value); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_OUTPUT_FILENAME: + outputFilename = value; + break; + + case OPT_OVERWRITE: + overwriteOutputFile = true; + break; + + case OPT_DEFAULT_GLYPH: + if (!ParseDefaultGlyph(value, defaultGlyph, regions)) + { + wprintf(L"Invalid character code specified with -%ls: (%ls)\n", LookupByValue(OPT_DEFAULT_GLYPH, g_Options), value); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + } + } + } + + if (fontHeight == 0) + { + wprintf(L"No value for required option -%ls\n", LookupByValue(OPT_HEIGHT, g_Options)); + PrintUsage(); + return 1; + } + + if (outputFilename == nullptr) + { + wprintf(L"No value for required options -%ls\n", LookupByValue(OPT_OUTPUT_FILENAME, g_Options)); + PrintUsage(); + return 1; + } + + if (!overwriteOutputFile) + { + if (GetFileAttributesW(outputFilename) != INVALID_FILE_ATTRIBUTES) + { + wprintf(L"\nERROR: Output file already exists, use -%ls to overwrite.\n", LookupByValue(OPT_OVERWRITE, g_Options)); + PrintUsage(); + return 1; + } + } + + try + { + LOGFONT logfont = {}; + logfont.lfHeight = fontHeight; + logfont.lfWidth = 0; + logfont.lfEscapement = 0; + logfont.lfOrientation = 0; + logfont.lfWeight = fontWeight; + logfont.lfItalic = useItalic; + logfont.lfUnderline = useUnderline; + logfont.lfStrikeOut = useStrikeOut; + logfont.lfCharSet = charset; + logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS; + logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + logfont.lfQuality = quality; + logfont.lfPitchAndFamily = uint8_t(pitch) | uint8_t(family); + logfont.lfFaceName[LF_FACESIZE]; + + if(typeFace) + wcscpy_s(logfont.lfFaceName, typeFace); + + // Create the glyphs + std::vector ggoGlyphs; + std::vector kerns; + Create_GGO_Glyphs( + &logfont, + ggoDepth, + regions, + kerns, + ggoGlyphs, + defaultGlyph); + + // Create the pixel buffer + size_t pixelBufferSize = 0; + std::unique_ptr pixels; + { + pixelBufferSize = CreatePixelBuffer(ggoGlyphs, nullptr, 0); + pixels = std::make_unique(pixelBufferSize); + CreatePixelBuffer(ggoGlyphs, pixels.get(), pixelBufferSize); + } + + // Compute the ascent and descent for the font + unsigned effectiveAscent = 0; + unsigned effectiveDescent = 0; + ComputeAscentDescent(ggoGlyphs, effectiveAscent, effectiveDescent); + + // Create the raster glyphs + std::vector rasterGlyphs; + rasterGlyphs.resize(ggoGlyphs.size()); + uint32_t pixelIndex = 0; + for (int i = 0; i < ggoGlyphs.size(); ++i) + { + rasterGlyphs[i].character = ggoGlyphs[i].GetCharacterCode(); + + auto& metrics = ggoGlyphs[i].GetMetrics(); + rasterGlyphs[i].blackBoxOriginX = int16_t(metrics.gmptGlyphOrigin.x); + rasterGlyphs[i].blackBoxOriginY = int16_t(metrics.gmptGlyphOrigin.y); + rasterGlyphs[i].blackBoxWidth = metrics.gmBlackBoxX; + rasterGlyphs[i].blackBoxHeight = metrics.gmBlackBoxY; + rasterGlyphs[i].cellIncX = metrics.gmCellIncX; + rasterGlyphs[i].cellIncY = metrics.gmCellIncY; + rasterGlyphs[i].pixelIndex = pixelIndex; + + + pixelIndex += GetStorageSize(metrics.gmBlackBoxX * metrics.gmBlackBoxY); + } + + // Create the kerning pairs + std::vector rasterKerns; + rasterKerns.resize(kerns.size()); + for (int i = 0; i < kerns.size(); ++i) + { + rasterKerns[i].first = kerns[i].wFirst; + rasterKerns[i].second = kerns[i].wSecond; + rasterKerns[i].amount = kerns[i].iKernAmount; + } + + // Write the RasterFont to the file + { + // Create the RasterFont + RasterFont rf(std::make_unique( + effectiveAscent, + effectiveDescent, + rasterGlyphs, + rasterKerns, + uint32_t(pixelBufferSize), + pixels.get(), + '\0')); + + rf.WriteToFile(outputFilename); + } + } + catch (std::exception &exn) + { + printf("Encountered an exception when trying to generate the font: \n%s", exn.what()); + return 1; + } + + return 0; +} + diff --git a/XDKSamples/Tools/RasterFontGen/pch.cpp b/XDKSamples/Tools/RasterFontGen/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d9f38c57d63f197d552a5283424f75f885bb1c2 --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/XDKSamples/Tools/RasterFontGen/pch.h b/XDKSamples/Tools/RasterFontGen/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..1d99129a606ab98bbd31603f6f1ab061d821a28a --- /dev/null +++ b/XDKSamples/Tools/RasterFontGen/pch.h @@ -0,0 +1,124 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#pragma warning(push) +#pragma warning(disable : 4005) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NODRAWTEXT +#define NOBITMAP +#define NOMCX +#define NOSERVICE +#define NOHELP +#pragma warning(pop) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace DX +{ + // formatted exception helper class + template + class exception_fmt : public std::exception + { + public: + exception_fmt(const char *msg, ...) + { + va_list args; + va_start(args, msg); + + vsprintf_s(exnBuffer, msg, args); + + va_end(args); + } + + virtual const char *what() const override + { + return exnBuffer; + } + + private: + static thread_local char exnBuffer[SIZE]; + }; + + template + thread_local char exception_fmt::exnBuffer[SIZE]; + + // Helper class for Win32 errors + class last_err_exception : public std::exception + { + public: + last_err_exception(uint32_t err) + : result(err) {} + + last_err_exception() + : result(0) + { + result = GetLastError(); + } + + virtual const char *what() const override + { + static char s_str[64] = {}; + sprintf_s(s_str, "Failure with last error of %08X", result); + return s_str; + } + + private: + uint32_t result; + }; + + // Convert the last error into an exception + inline void ThrowLastError() + { + throw last_err_exception(); + } + + template + inline void ThrowLastErrWhenFalse(T result) + { + if (!result) + { + throw last_err_exception(); + } + } + + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} // namespace DX diff --git a/XDKSamples/Tools/RasterFontGen/readme.docx b/XDKSamples/Tools/RasterFontGen/readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..f333fac76efd68b81bac6bad96aaee6bd517a125 Binary files /dev/null and b/XDKSamples/Tools/RasterFontGen/readme.docx differ diff --git a/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.sln b/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.sln new file mode 100644 index 0000000000000000000000000000000000000000..b5ce4019bfdf360e33587faa93d57ebe97c15e8d --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RasterFontViewer", "RasterFontViewer.vcxproj", "{9901FA10-9237-4AF0-9505-D4AE9735E31F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9901FA10-9237-4AF0-9505-D4AE9735E31F}.Debug|x64.ActiveCfg = Debug|x64 + {9901FA10-9237-4AF0-9505-D4AE9735E31F}.Debug|x64.Build.0 = Debug|x64 + {9901FA10-9237-4AF0-9505-D4AE9735E31F}.Release|x64.ActiveCfg = Release|x64 + {9901FA10-9237-4AF0-9505-D4AE9735E31F}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.vcxproj b/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..39cb308a52fd5e2398450d9e00da1fccc28c0bda --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.vcxproj @@ -0,0 +1,112 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {9901FA10-9237-4AF0-9505-D4AE9735E31F} + Win32Proj + RasterFontViewer + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + true + + + false + + + + Use + pch.h + ..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + Use + pch.h + ..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.vcxproj.filters b/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..421bd379ee0bbf0aa994600f80780bc7dca67a50 --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/RasterFontViewer.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG Tool Kit + + + + + {44506a5a-d3ec-4ca5-be57-6245d14d42b1} + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontViewer/TestWindow.cpp b/XDKSamples/Tools/RasterFontViewer/TestWindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f3ebfdd8ff732c94639f1d5249e6b3ef87b7f84 --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/TestWindow.cpp @@ -0,0 +1,243 @@ +//-------------------------------------------------------------------------------------- +// TestWindow.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "TestWindow.h" + +namespace ATG +{ + LPCWSTR g_szAppName = L"TestWindowApp"; + LPCWSTR g_szClassName = L"TestWindowClass"; +} + +using namespace ATG; + +TestWindow::TestWindow(const PaintCallback & onPaint) + : m_onPaint(onPaint) +{ + HINSTANCE hInstance = GetModuleHandle(nullptr); + + // Register class and create window + { + // Register class + WNDCLASSEX wcex = {}; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = s_WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, L"IDI_ICON"); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = g_szClassName; + wcex.hIconSm = LoadIcon(wcex.hInstance, L"IDI_ICON"); + + DX::ThrowLastErrWhenFalse(RegisterClassEx(&wcex)); + + // Create window + int w = 1024; + int h = 768; + + RECT rc; + rc.top = 0; + rc.left = 0; + rc.right = static_cast(w); + rc.bottom = static_cast(h); + + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + + HWND hwnd = CreateWindowEx(0, g_szClassName, g_szAppName, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, + nullptr); + + // Change to CreateWindowEx(WS_EX_TOPMOST, L"SimpleTrianglePCWindowClass", g_szAppName, WS_POPUP, + // to default to fullscreen. + + DX::ThrowLastErrWhenFalse(hwnd); + + + ShowWindow(hwnd, SW_SHOWDEFAULT); + // Change nCmdShow to SW_SHOWMAXIMIZED to default to fullscreen. + + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(this)); + + GetClientRect(hwnd, &rc); + } + + // Main message loop + MSG msg = { 0 }; + while (WM_QUIT != msg.message) + { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + } + } +} + +LRESULT TestWindow::s_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + auto thisTestWindow = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + return thisTestWindow->WndProc(hWnd, message, wParam, lParam); +} + +LRESULT ATG::TestWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static bool s_in_sizemove = false; + static bool s_in_suspend = false; + static bool s_minimized = false; + static bool s_fullscreen = false; + + switch (message) + { + case WM_PAINT: + OnPaint(hWnd); + break; + + case WM_SIZE: + if (wParam == SIZE_MINIMIZED) + { + if (!s_minimized) + { + s_minimized = true; + s_in_suspend = true; + } + } + else if (s_minimized) + { + s_minimized = false; + s_in_suspend = false; + } + else if (!s_in_sizemove) + { + } + break; + + case WM_ENTERSIZEMOVE: + s_in_sizemove = true; + break; + + case WM_EXITSIZEMOVE: + s_in_sizemove = false; + break; + + case WM_GETMINMAXINFO: + { + auto info = reinterpret_cast(lParam); + info->ptMinTrackSize.x = 320; + info->ptMinTrackSize.y = 200; + } + break; + + case WM_ACTIVATEAPP: + break; + + case WM_POWERBROADCAST: + switch (wParam) + { + case PBT_APMQUERYSUSPEND: + s_in_suspend = true; + return TRUE; + + case PBT_APMRESUMESUSPEND: + if (!s_minimized) + { + s_in_suspend = false; + } + return TRUE; + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_INPUT: + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEWHEEL: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + case WM_MOUSEHOVER: + break; + + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + break; + + case WM_SYSKEYDOWN: + if (wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000) + { + // Implements the classic ALT+ENTER fullscreen toggle + if (s_fullscreen) + { + SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); + SetWindowLongPtr(hWnd, GWL_EXSTYLE, 0); + + int width = 800; + int height = 600; + + ShowWindow(hWnd, SW_SHOWNORMAL); + + SetWindowPos(hWnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); + } + else + { + SetWindowLongPtr(hWnd, GWL_STYLE, 0); + SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST); + + SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + + ShowWindow(hWnd, SW_SHOWMAXIMIZED); + } + + s_fullscreen = !s_fullscreen; + } + break; + + case WM_MENUCHAR: + // A menu is active and the user presses a key that does not correspond + // to any mnemonic or accelerator key. Ignore so we don't produce an error beep. + return MAKELRESULT(0, MNC_CLOSE); + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +void TestWindow::OnPaint(HWND hWnd) +{ + PAINTSTRUCT ps; + HDC hDC; + + hDC = BeginPaint(hWnd, &ps); + + RECT rect; + if (!GetClientRect(hWnd, &rect)) + { + return; + } + + HBRUSH br = CreateSolidBrush(RGB(0x00, 0x00, 0x00)); + FillRect(hDC, &rect, br); + + m_onPaint(hDC); + + DeleteObject(br); + + EndPaint(hWnd, &ps); +} diff --git a/XDKSamples/Tools/RasterFontViewer/TestWindow.h b/XDKSamples/Tools/RasterFontViewer/TestWindow.h new file mode 100644 index 0000000000000000000000000000000000000000..2e9957e7870efbd59f442705f3d4d7d2f3e0027f --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/TestWindow.h @@ -0,0 +1,29 @@ +//-------------------------------------------------------------------------------------- +// TestWindow.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include + +namespace ATG +{ + // Window class for displaying and testing GDI graphics + class TestWindow + { + public: + using PaintCallback = std::function; + TestWindow(const PaintCallback &onPaint); + + private: + static LRESULT CALLBACK s_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + void OnPaint(HWND hWnd); + + PaintCallback m_onPaint; + }; + +} // namespace ATG \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontViewer/Visualization.cpp b/XDKSamples/Tools/RasterFontViewer/Visualization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b77204a9d0ae4fe4d3085144a96b07f6c425136 --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/Visualization.cpp @@ -0,0 +1,238 @@ +//-------------------------------------------------------------------------------------- +// Visualization.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include "Visualization.h" + +#include "FrontPanel\RasterFont.h" + +using namespace ATG; + +void ATG::DrawDebugBox(HDC hDC, const RECT & r, COLORREF color) +{ + HGDIOBJ stockPen = GetStockObject(DC_PEN); + HGDIOBJ oldPen = SelectObject(hDC, stockPen); + COLORREF oldColor = SetDCPenColor(hDC, color); + + int oldMode = SetBkMode(hDC, OPAQUE); + + MoveToEx(hDC, r.left, r.top, nullptr); + LineTo(hDC, r.right, r.top); + LineTo(hDC, r.right, r.bottom); + LineTo(hDC, r.left, r.bottom); + LineTo(hDC, r.left, r.top); + + SetBkMode(hDC, oldMode); + SetDCPenColor(hDC, oldColor); + SelectObject(hDC, oldPen); + + DeleteObject(stockPen); +} + +namespace +{ + void DrawOneGlyph( + const RasterGlyphSheet &glyphSheet, + const RasterGlyphSheet::RasterGlyph &glyph, + + HDC memDC, + RECT &r, + unsigned int &baseline, + unsigned int &col, + unsigned int &row, + + unsigned int tableColumns, + unsigned int maxCellHeight, + unsigned int maxCellWidth, + unsigned int vertPadding, + unsigned int horzPadding) + { + // Render a debug box around the cell containing the glyph + RECT cellRect; + cellRect.top = r.top; + cellRect.bottom = cellRect.top + maxCellHeight + 2; + + cellRect.left = r.left; + cellRect.right = cellRect.left + maxCellWidth + 2; + + DrawDebugBox(memDC, cellRect, RGB(255, 0, 0)); + + // Render debug box representing the black box of the glyph + RECT bbRect; + bbRect.top = baseline - glyph.blackBoxOriginY; + bbRect.bottom = bbRect.top + glyph.blackBoxHeight + 1; + bbRect.left = r.left + 1; + bbRect.right = bbRect.left + glyph.blackBoxWidth + 1; + + DrawDebugBox(memDC, bbRect, RGB(0, 255, 0)); + + //Render the glyph pixels + glyphSheet.ForEachGlyphPixel(glyph, bbRect.left + 1, bbRect.top + 1, [&](unsigned x, unsigned y, uint8_t color) { + uint8_t clr = !!color * 255; + if (clr) + SetPixel(memDC, x, y, RGB(clr, clr, clr)); + }); + + // Advance to the next cell + ++col; + r.left += maxCellWidth + horzPadding; + if (col == tableColumns) + { + col = 0; + r.left = horzPadding; + ++row; + r.top += maxCellHeight + vertPadding; + baseline = r.top + glyphSheet.GetEffectiveAscent(); + } + + r.right = r.left + maxCellWidth; + r.bottom = r.top + maxCellHeight; + + } + +} // ANONYMOUS namespace + +HBITMAP ATG::DrawRasterGlyphSheet(const RasterGlyphSheet &glyphSheet, const std::vector ®ions) +{ + // Set up a memory device context for laying out the glyph sheet + HDC hDC = GetDC(nullptr); + HDC memDC = CreateCompatibleDC(hDC); + + // Figure out the set of glyphs to draw + std::vector charsToDraw; + { + std::set setToDraw; + for (auto itr = regions.begin(); itr != regions.end(); ++itr) + { + auto& range = *itr; + for (wchar_t wc = range.wcLow; wc < range.wcLow + range.cGlyphs; ++wc) + { + auto glyph = glyphSheet.FindGlyph(wc); + if (glyph) + { + setToDraw.insert(wc); + } + } + } + for (auto itr = setToDraw.begin(); itr != setToDraw.end(); ++itr) + { + charsToDraw.push_back(*itr); + } + } + + std::sort(charsToDraw.begin(), charsToDraw.end()); + + unsigned glyphCount = charsToDraw.empty() ? unsigned(glyphSheet.GetGlyphCount()) : unsigned(charsToDraw.size()); + unsigned maxCellWidth = 0; + unsigned maxCellHeight = glyphSheet.GetEffectiveAscent() + glyphSheet.GetEffectiveDescent(); + + if (charsToDraw.empty()) + { + for (auto itr = glyphSheet.begin(); itr != glyphSheet.end(); ++itr) + { + auto& glyph = *itr; + maxCellWidth = std::max(maxCellWidth, unsigned(glyph.blackBoxWidth)); + } + } + else + { + std::for_each(charsToDraw.begin(), charsToDraw.end(), [&](wchar_t wc) { + auto glyph = *glyphSheet.FindGlyph(wc); + maxCellWidth = std::max(maxCellWidth, unsigned(glyph.blackBoxWidth)); + }); + } + + if (maxCellWidth == 0 || maxCellHeight == 0) + { + throw DX::exception_fmt<64>("The glyph sheet doesn't contain any glyphs."); + } + + // Pack the glyphs into a square bitmap + unsigned lengthInPixels = unsigned(ceil(sqrt(maxCellHeight * maxCellWidth * glyphCount))); + unsigned tableColumns = lengthInPixels / maxCellWidth; + unsigned tableRows = lengthInPixels / maxCellHeight ? lengthInPixels / maxCellHeight : 1; + + while (tableColumns * tableRows < glyphCount) + { + ++tableColumns; + } + + unsigned horzPadding = 4; + unsigned vertPadding = 4; + + unsigned w = tableColumns * maxCellWidth + (tableColumns + 1) * horzPadding; + unsigned h = tableRows * maxCellHeight + (tableRows + 1) * vertPadding; + + HBITMAP fontBitmap = CreateCompatibleBitmap(hDC, w, h); + SelectObject(memDC, fontBitmap); + + RECT r; + r.top = 0; + r.left = 0; + r.right = w; + r.bottom = h; + + FillRect(memDC, &r, (HBRUSH)GetStockObject(BLACK_BRUSH)); + + SetBkMode(memDC, TRANSPARENT); + SetTextColor(memDC, RGB(255, 255, 255)); // TODO: Do we need this anymore? + + r.top = vertPadding; + r.bottom = r.top + maxCellHeight; + r.left = horzPadding; + r.right = r.left + maxCellWidth; + + unsigned int col = 0; + unsigned int row = 0; + unsigned baseline = r.top + glyphSheet.GetEffectiveAscent(); + + if (charsToDraw.empty()) + { + for (auto itr = glyphSheet.begin(); itr != glyphSheet.end(); ++itr) + { + DrawOneGlyph( + glyphSheet, + *itr, + memDC, + r, + baseline, + col, + row, + tableColumns, + maxCellHeight, + maxCellWidth, + vertPadding, + horzPadding); + } + } + else + { + for (auto itr = charsToDraw.begin(); itr != charsToDraw.end(); ++itr) + { + auto& glyph = *glyphSheet.FindGlyph(*itr); + DrawOneGlyph( + glyphSheet, + glyph, + memDC, + r, + baseline, + col, + row, + tableColumns, + maxCellHeight, + maxCellWidth, + vertPadding, + horzPadding); + + } + } + + DeleteObject(memDC); + return fontBitmap; + + +} diff --git a/XDKSamples/Tools/RasterFontViewer/Visualization.h b/XDKSamples/Tools/RasterFontViewer/Visualization.h new file mode 100644 index 0000000000000000000000000000000000000000..3142dc523c0c2a3de5f93b9d19282e6e63b84554 --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/Visualization.h @@ -0,0 +1,21 @@ +//-------------------------------------------------------------------------------------- +// Visualization.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include +#include +#include + +namespace ATG +{ + class RasterGlyphSheet; + + void DrawDebugBox(HDC hDC, const RECT &r, COLORREF color); + + HBITMAP DrawRasterGlyphSheet(const RasterGlyphSheet &glyphSheet, const std::vector ®ions); + +} // namespace ATG \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontViewer/main.cpp b/XDKSamples/Tools/RasterFontViewer/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37983f59a965779e934e0f749e019731204306fc --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/main.cpp @@ -0,0 +1,167 @@ +//-------------------------------------------------------------------------------------- +// main.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" + +#include +#include + +#include "FrontPanel\RasterFont.h" + +#include "CommandLineHelpers.h" +#include "TestWindow.h" +#include "Visualization.h" + +using namespace ATG; + +namespace +{ + enum OPTIONS : uint64_t + { + OPT_CHARACTER_REGION = 1, + OPT_MAX + }; + + static_assert(OPT_MAX <= 64, "Options must fit into a uint64_t bitfield"); + + + const SValue g_Options[] = + { + { L"cr", OPT_CHARACTER_REGION }, + }; + + void PrintLogo() + { + wprintf(L"Microsoft (R) Raster Font Viewer for for Xbox One\n"); + wprintf(L"Copyright (C) Microsoft Corp. All rights reserved.\n"); +#ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); +#endif + wprintf(L"\n"); + } + + void PrintUsage() + { + PrintLogo(); + + wprintf(L"Usage: rasterfontgen [options] \n\n"); + wprintf(L" -cr: Character region. Specifies a range of unicode code points to include in the output.\n"); + wprintf(L" Examples: -cr:a-z -cr:0x1200-0x1250 -cr:0x1234\n"); + } +} // ANONYMOUS namespace + +int wmain(int argc, wchar_t *argv[]) +{ + // Parameters and defaults + const wchar_t *outputFilename = nullptr; + std::vector regions; + + unsigned individualOptions = 0; + + for (int argIdx = 1; argIdx < argc; ++argIdx) + { + wchar_t *arg = argv[argIdx]; + + if (('-' == arg[0]) || ('/' == arg[0])) + { + arg++; + + wchar_t *value = nullptr; + for (value = arg; *value && (':' != *value); ++value); + if (*value) + *value++ = 0; + + unsigned option = 0; + if (!LookupByName(arg, g_Options, option) || (individualOptions & (1 << option))) + { + PrintUsage(); + return 1; + } + + if (option != OPT_CHARACTER_REGION) + { + individualOptions |= (1 << option); + } + + // Handle options with an additional value parameter + switch (option) + { + case OPT_CHARACTER_REGION: + if (!*value) + { + if (argIdx + 1 >= argc) + { + PrintUsage(); + return 1; + } + + ++argIdx; + value = argv[argIdx]; + } + break; + } + + switch (option) + { + case OPT_CHARACTER_REGION: + if (!ParseCharacterRegion(value, regions)) + { + wprintf(L"Invalid character region value specified with -%ls: (%ls)\n", LookupByValue(OPT_CHARACTER_REGION, g_Options), value); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + } + + } + else if(outputFilename) + { + wprintf(L"Output file already specified: %ls.\n(Found something else: %ls\n", outputFilename, arg); + PrintUsage(); + return 1; + } + else + { + outputFilename = arg; + } + } + + if (!outputFilename) + { + PrintUsage(); + return 1; + } + + try + { + RasterFont rf(outputFilename); + + HBITMAP fontBitmap = DrawRasterGlyphSheet(rf.GetGlyphs(), regions); + + TestWindow([&fontBitmap](HDC hDC) + { + BITMAP bmData = {}; + GetObject(fontBitmap, sizeof(BITMAP), &bmData); + + HDC memDC = CreateCompatibleDC(hDC); + SelectObject(memDC, fontBitmap); + + BitBlt(hDC, 0, 0, bmData.bmWidth, bmData.bmHeight, memDC, 0, 0, SRCCOPY); + + DeleteObject(memDC); + }); + + DeleteObject(fontBitmap); + + } + catch (std::exception &exn) + { + printf("Encountered an excption when trying to load the font: \n%s", exn.what()); + } + + return 0; +} \ No newline at end of file diff --git a/XDKSamples/Tools/RasterFontViewer/pch.cpp b/XDKSamples/Tools/RasterFontViewer/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d9f38c57d63f197d552a5283424f75f885bb1c2 --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/XDKSamples/Tools/RasterFontViewer/pch.h b/XDKSamples/Tools/RasterFontViewer/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..c81821cab59ba7033536428c7cea8b77592f6ae7 --- /dev/null +++ b/XDKSamples/Tools/RasterFontViewer/pch.h @@ -0,0 +1,126 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#pragma warning(push) +#pragma warning(disable : 4005) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NODRAWTEXT +#define NOBITMAP +#define NOMCX +#define NOSERVICE +#define NOHELP +#pragma warning(pop) + +#include +#include +#include +#include +#include +#include + +#include + +namespace DX +{ + // formatted exception helper class + template + class exception_fmt : public std::exception + { + public: + exception_fmt(const char *msg, ...) + { + va_list args; + va_start(args, msg); + + vsprintf_s(exnBuffer, msg, args); + + va_end(args); + } + + virtual const char *what() const override + { + return exnBuffer; + } + + private: + static thread_local char exnBuffer[SIZE]; + }; + + template + thread_local char exception_fmt::exnBuffer[SIZE]; + + // Helper class for Win32 errors + class last_err_exception : public std::exception + { + public: + last_err_exception(uint32_t err) + : result(err) {} + + last_err_exception() + : result(0) + { + result = GetLastError(); + } + + virtual const char *what() const override + { + static char s_str[64] = {}; + sprintf_s(s_str, "Failure with last error of %08X", result); + return s_str; + } + + private: + uint32_t result; + }; + + // Convert the last error into an exception + inline void ThrowLastError() + { + throw last_err_exception(); + } + + template + inline void ThrowLastErrWhenFalse(T result) + { + if (!result) + { + throw last_err_exception(); + } + } + + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} // namespace DX + + + +// TODO: reference additional headers your program requires here diff --git a/XDKSamples/Tools/RasterFontViewer/readme.docx b/XDKSamples/Tools/RasterFontViewer/readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..fb931627708f803938dd5d31e1e07a608a8f797b Binary files /dev/null and b/XDKSamples/Tools/RasterFontViewer/readme.docx differ diff --git a/XDKSamples/Tools/SymbolProxyClient/Assets/Logo.png b/XDKSamples/Tools/SymbolProxyClient/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c0fc7df8cd1c677853b40c147a5a57a0e733cea6 Binary files /dev/null and b/XDKSamples/Tools/SymbolProxyClient/Assets/Logo.png differ diff --git a/XDKSamples/Tools/SymbolProxyClient/Assets/SmallLogo.png b/XDKSamples/Tools/SymbolProxyClient/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c352cc68fce5c0410210abbe08188ef1159ec0d2 Binary files /dev/null and b/XDKSamples/Tools/SymbolProxyClient/Assets/SmallLogo.png differ diff --git a/XDKSamples/Tools/SymbolProxyClient/Assets/SplashScreen.png b/XDKSamples/Tools/SymbolProxyClient/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..96fede95bd502a1bb17ca64976c397455711f69a Binary files /dev/null and b/XDKSamples/Tools/SymbolProxyClient/Assets/SplashScreen.png differ diff --git a/XDKSamples/Tools/SymbolProxyClient/Assets/StoreLogo.png b/XDKSamples/Tools/SymbolProxyClient/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..62cd3f2b19b529135b630cb1647e7325d3b571ef Binary files /dev/null and b/XDKSamples/Tools/SymbolProxyClient/Assets/StoreLogo.png differ diff --git a/XDKSamples/Tools/SymbolProxyClient/Assets/WideLogo.png b/XDKSamples/Tools/SymbolProxyClient/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..02ba097439184f85fe04530259c8dab9dc303988 Binary files /dev/null and b/XDKSamples/Tools/SymbolProxyClient/Assets/WideLogo.png differ diff --git a/XDKSamples/Tools/SymbolProxyClient/CallStack.cpp b/XDKSamples/Tools/SymbolProxyClient/CallStack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c04436b9ec55e8f48a60fd3484129910e3b396f --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/CallStack.cpp @@ -0,0 +1,299 @@ +//-------------------------------------------------------------------------------------- +// CallStack.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "pch.h" +#include "CallStack.h" +#include +#include +#include +#include + +using namespace CallStack; + +size_t CallStack::CaptureBackTraceFromCurrentThread(void** addresses, HMODULE* modules, size_t framesToCapture) +{ + DWORD dwStackHash = 0; + static const uint32_t FRAMES_TO_SKIP = 1; + size_t numCapturedFrames = RtlCaptureStackBackTrace(FRAMES_TO_SKIP, static_cast(framesToCapture), addresses, &dwStackHash); + + for (uint32_t i = 0; i < numCapturedFrames; ++i) + { + uint64_t baseAddress = 0; + RUNTIME_FUNCTION *runtimeFunction = ::RtlLookupFunctionEntry(reinterpret_cast(addresses[i]), &baseAddress, nullptr); + + if (runtimeFunction == nullptr) + { + // If we don't have a RUNTIME_FUNCTION, then we've encountered + // a leaf function. Adjust the stack data appropriately. + if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(addresses[i]), &modules[i])) + { + modules[i] = 0; + } + } + else + { + modules[i] = reinterpret_cast(baseAddress); + } + } + + return numCapturedFrames; +} + +size_t CallStack::CaptureBackTraceFromContext(CONTEXT *contextRecord, void** addresses, HMODULE* modules, size_t framesToCapture) +{ + if (contextRecord == nullptr) + { + return 0; + } + + CONTEXT ctx = *contextRecord; + + uint64_t baseAddress = 0; + + KNONVOLATILE_CONTEXT_POINTERS NvContext = {}; + void* handlerData = nullptr; + uint64_t establisherFrame = 0; + + size_t numCapturedFrames = 0; + do + { + RUNTIME_FUNCTION *runtimeFunction = RtlLookupFunctionEntry(ctx.Rip, &baseAddress, nullptr); + + modules[numCapturedFrames] = (HMODULE)baseAddress; + addresses[numCapturedFrames] = reinterpret_cast(ctx.Rip); + ++numCapturedFrames; + + if (runtimeFunction) + { + // unwind based on current context + RtlVirtualUnwind( + UNW_FLAG_NHANDLER, + baseAddress, + ctx.Rip, + runtimeFunction, + &ctx, + &handlerData, + &establisherFrame, + &NvContext); + } + else + { + // If we don't have a RUNTIME_FUNCTION, then we've encountered + // a leaf function. Adjust the stack appropriately. + ctx.Rip = *reinterpret_cast(ctx.Rsp); + ctx.Rsp += 8; + } + } while (numCapturedFrames < framesToCapture && ctx.Rip != 0); + + return numCapturedFrames; +} + +size_t CallStack::GetFrameCountFromContext(CONTEXT *contextRecord) +{ + if (contextRecord == nullptr) + { + return 0; + } + + CONTEXT ctx = *contextRecord; + + uint64_t baseAddress = 0; + + KNONVOLATILE_CONTEXT_POINTERS NvContext = {}; + void* handlerData = nullptr; + uint64_t establisherFrame = 0; + + size_t numCapturedFrames = 0; + do + { + RUNTIME_FUNCTION *runtimeFunction = RtlLookupFunctionEntry(ctx.Rip, &baseAddress, nullptr); + + ++numCapturedFrames; + + if (runtimeFunction) + { + // unwind based on current context + RtlVirtualUnwind( + UNW_FLAG_NHANDLER, + baseAddress, + ctx.Rip, + runtimeFunction, + &ctx, + &handlerData, + &establisherFrame, + &NvContext); + } + else + { + // If we don't have a RUNTIME_FUNCTION, then we've encountered + // a leaf function. Adjust the stack appropriately. + ctx.Rip = *reinterpret_cast(ctx.Rsp); + ctx.Rsp += 8; + } + } while (ctx.Rip != 0); + + return numCapturedFrames; +} + +namespace +{ + static const size_t MAX_FRAMES_TO_CAPTURE = 64; + void* g_addresses[MAX_FRAMES_TO_CAPTURE]; + HMODULE g_modules[MAX_FRAMES_TO_CAPTURE]; + ATG::CriticalSectionLockable g_frameDataMutex; +} // anonymous namespace + +void BackTrace::Clear() +{ + m_frames.clear(); + memset(g_addresses, 0, sizeof(g_addresses)); + memset(g_modules, 0, sizeof(g_modules)); +} + +size_t BackTrace::CaptureCurrentThread() +{ + std::lock_guard scopedLock(g_frameDataMutex); + Clear(); + size_t numCapturedFrames = CaptureBackTraceFromCurrentThread(g_addresses, g_modules, MAX_FRAMES_TO_CAPTURE); + m_frames.resize(numCapturedFrames); + for (size_t i = 0; i < numCapturedFrames; ++i) + { + frame_data &fd = m_frames[i]; + fd.moduleHandle = g_modules[i]; + fd.relativeVirtualAddress = reinterpret_cast(g_addresses[i]) - reinterpret_cast(g_modules[i]); + } + return numCapturedFrames; +} + +size_t BackTrace::CaptureCrossThread(HANDLE whichThread) +{ + if (IsCurrentThread(whichThread)) + { + return CaptureCurrentThread(); + } + + { + std::lock_guard scopedLock(g_frameDataMutex); + size_t numCapturedFrames = 0; + + CONTEXT ctx = {}; + ctx.ContextFlags = CONTEXT_FULL; + { + DX::ThreadSuspender susp(whichThread); + if (GetThreadContext(whichThread, &ctx)) + { + // Only want to suspend the thread for the duration of the capture + numCapturedFrames = CaptureBackTraceFromContext(&ctx, g_addresses, g_modules, MAX_FRAMES_TO_CAPTURE); + } + } + + m_frames.resize(numCapturedFrames); + for (size_t i = 0; i < numCapturedFrames; ++i) + { + frame_data &fd = m_frames[i]; + fd.moduleHandle = g_modules[i]; + fd.relativeVirtualAddress = reinterpret_cast(g_addresses[i]) - reinterpret_cast(g_modules[i]); + } + return numCapturedFrames; + } +} + +HRESULT BackTrace::Resolve(unsigned flags) +{ + std::vector rawFrames; + size_t numFrames = m_frames.size(); + + if (numFrames == 0) + { + assert(numFrames > 0); // Probably forgot to capture frames (should at least have a frame for the capture method -- right?) + return E_NOT_VALID_STATE; + } + + rawFrames.resize(numFrames); + for (size_t i = 0; i < numFrames; ++i) + { + rawFrames[i] = m_frames[i].relativeVirtualAddress + (uint64_t)m_frames[i].moduleHandle; + } + + HRESULT hr = S_OK; + if (SUCCEEDED(hr) && (flags & CAPTURE_FLAGS_SYMBOL_INFO) == CAPTURE_FLAGS_SYMBOL_INFO) + { + hr = ResolveSymbolInfo(rawFrames.size(), &rawFrames[0]); + } + + if (SUCCEEDED(hr) && (flags & CAPTURE_FLAGS_SOURCE_INFO) == CAPTURE_FLAGS_SOURCE_INFO) + { + hr = ResolveSourceInfo(rawFrames.size(), &rawFrames[0]); + } + return hr; +} + +HRESULT BackTrace::ResolveSymbolInfo(size_t numFrames, ULONG_PTR *addresses) +{ + ResolutionContext ctx; + ctx.whichFrame = 0; + ctx.frames = &m_frames[0]; + + return ::GetSymbolFromAddress(ResolveDisposition::DefaultPriority, static_cast(numFrames), addresses, s_SymCallback, &ctx); +} + +HRESULT BackTrace::ResolveSourceInfo(size_t numFrames, ULONG_PTR *addresses) +{ + ResolutionContext ctx; + ctx.whichFrame = 0; + ctx.frames = &m_frames[0]; + + return ::GetSourceLineFromAddress(ResolveDisposition::DefaultPriority, static_cast(numFrames), addresses, s_SrcCallback, &ctx); +} + +BOOL BackTrace::s_SymCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT symbolResult, PCWSTR symName, ULONG offset) +{ + UNREFERENCED_PARAMETER(symbolAddress); + + if (context == nullptr) + { + assert(context != nullptr); + // Yikes!! (this could only be a programming error) + return FALSE; + } + + ResolutionContext &ctx = *reinterpret_cast(context); + unsigned i = ctx.whichFrame++; + ctx.frames[i].symbolResult = symbolResult; + if (SUCCEEDED(symbolResult)) + { + ctx.frames[i].symbolName = symName; + ctx.frames[i].symbolOffset = offset; + } + return TRUE; +} + +BOOL BackTrace::s_SrcCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT sourceResult, PCWSTR filepath, ULONG lineNumber) +{ + UNREFERENCED_PARAMETER(symbolAddress); + + if (context == nullptr) + { + assert(context != nullptr); + // Yikes!! (this could only be a programming error) + return FALSE; + } + + ResolutionContext &ctx = *reinterpret_cast(context); + unsigned i = ctx.whichFrame++; + ctx.frames[i].sourceResult = sourceResult; + if (SUCCEEDED(sourceResult)) + { + ctx.frames[i].sourceFileName = filepath; + ctx.frames[i].sourceLineNumber = lineNumber; + } + return TRUE; +} + +bool BackTrace::IsCurrentThread(HANDLE whichThread) const +{ + return GetThreadId(whichThread) == ::GetCurrentThreadId(); +} diff --git a/XDKSamples/Tools/SymbolProxyClient/CallStack.h b/XDKSamples/Tools/SymbolProxyClient/CallStack.h new file mode 100644 index 0000000000000000000000000000000000000000..b4a25a5032663db21fce8b24c2d383e5b1236746 --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/CallStack.h @@ -0,0 +1,155 @@ +//-------------------------------------------------------------------------------------- +// File: CallStack.h +// +// Diagnostic helpers for working with callstacks +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright(c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +namespace CallStack +{ + // Capture the backtrace for the current thread + // Parameters: + // addresses -- receives the return addresses from each stack frame in the current call stack + // modules -- receives the module handle corresponding to the return address for each stack frame + // framesToCapture -- indicates the number of frames to capture + // Return value: + // Returns the number of frames that were captured + // Note: the caller must allocate enough space in addresses and modules to accomodate the number of + // frames specified by framesToCapture + size_t CaptureBackTraceFromCurrentThread(void** addresses, HMODULE *modules, size_t framesToCapture); + + // Capture the backtrace starting with the provided context record. + // Parameters: + // contextRecord: address of a context record (register data) + // addresses -- receives the return addresses from each stack frame in the current call stack + // modules -- receives the module handle corresponding to the return address for each stack frame + // framesToCapture -- indicates the number of frames to capture + // Return value: + // Returns the number of frames that were captured + // Note: the caller must allocate enough space in addresses and modules to accomodate the number of + // frames specified by framesToCapture + size_t CaptureBackTraceFromContext(CONTEXT *contextRecord, void** addresses, HMODULE* modules, size_t framesToCapture); + + // Count the number of stack frames in the callstack starting with the provided context record. + // Parameters: + // contextRecord: address of a context record (register data) + // Return value: + // Returns the number of frames + // Remarks: + // This is provided, for "completeness", so that you may allocate memory for a backtrace. I.e first you call GetFrameCountFromContext, + // then you allocate space for that many addresses and module handles, finally, you call CaptureBackTraceFromContext. + // Bear in mind that it is not quite that easy!: + // In particular, you must "freeze" the thread corresponding to the provided context record during the entire process. + // Put differently, you cannot let the thread add and remove stack frames (otherwise the count will be wrong.) This + // becomes problematic because in the case when the thread is holding a lock to the heap, then if you try to allocate + // from the same heap it will cause a deadlock. + // The takeaway is that you will need a separate allocation mechanism (e.g. a "debug heap") if you are going to try + // to use this pattern. An alternative, simpler, approach is to just set asside some static memory that is "big enough" + // for most callstacks. This is the strategy used by the BackTrace class below. + size_t GetFrameCountFromContext(CONTEXT *contextRecord); + + // Utility for capturing a backtrace + class BackTrace + { + public: + BackTrace() = default; + + // Data for a stack frame + struct frame_data + { + frame_data() + : moduleHandle(0) + , relativeVirtualAddress(0) + , symbolOffset(0) + , sourceLineNumber(0) + , symbolResult(E_NOT_SET) + , sourceResult(E_NOT_SET) + {} + + // The module handle also happens to be numerically identical to the base address of the module + HMODULE moduleHandle; + + // The relative virual address is the offset of the symbol from the module base address + uint64_t relativeVirtualAddress; + + // symbol name information + std::wstring symbolName; + uint64_t symbolOffset; + + // source file information + std::wstring sourceFileName; + uint64_t sourceLineNumber; + + // error information from the symbol proxy + HRESULT symbolResult; + HRESULT sourceResult; + }; + + // Number of frames in the backtrace + size_t size() const + { + return m_frames.size(); + } + + // Access to frames by index + const frame_data &operator [] (unsigned idx) const + { + if (idx < m_frames.size()) + { + return m_frames[idx]; + } + throw std::out_of_range("Index is out of range"); + } + + // Capture a backtrace from the current thread + // Result: + // Returns the number of frames captured + size_t CaptureCurrentThread(); + + // Capture a backtrace from the thread specified by the provided handle + // Parameter: + // whichThread -- specifies the thread for which to capture a backtrace + // Result: + // Returns the number of frames captured + size_t CaptureCrossThread(HANDLE whichThread); + + static const unsigned CAPTURE_FLAGS_NONE = 0; + static const unsigned CAPTURE_FLAGS_SYMBOL_INFO = 0x1; // Use this to resolve symbol name and offset + static const unsigned CAPTURE_FLAGS_SOURCE_INFO = 0x2; // Use this to resolve source filename and line number + static const unsigned CAPTURE_FLAGS_DEFAULT = CAPTURE_FLAGS_SYMBOL_INFO | CAPTURE_FLAGS_SOURCE_INFO; + + // Resolves the symbol information for the backtrace + // Parameter: + // captureFlags -- indicates which symbol information to resolve + HRESULT Resolve(unsigned captureFlags = CAPTURE_FLAGS_DEFAULT); + + private: + void Clear(); + bool IsCurrentThread(HANDLE whichThread) const; + + std::vector m_frames; + + HRESULT ResolveSymbolInfo(size_t numFrames, ULONG_PTR *addresses); + HRESULT ResolveSourceInfo(size_t numFrames, ULONG_PTR *addresses); + + struct ResolutionContext + { + unsigned whichFrame; + frame_data *frames; + }; + static BOOL CALLBACK s_SymCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT symbolResult, PCWSTR symName, ULONG offset); + static BOOL CALLBACK s_SrcCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT sourceResult, PCWSTR filepath, ULONG lineNumber); + }; +} // namespace CallStack diff --git a/XDKSamples/Tools/SymbolProxyClient/DeviceResources.cpp b/XDKSamples/Tools/SymbolProxyClient/DeviceResources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7647a07a0297b66a415ef0759d1eaeb0ec31288 --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/DeviceResources.cpp @@ -0,0 +1,215 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.X Xbox One Monolithic Runtime) +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace DX; + +using Microsoft::WRL::ComPtr; + +// Constructor for DeviceResources. +DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_1), + m_outputSize{0, 0, 1920, 1080} +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#ifdef _DEBUG + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; +#elif defined(PROFILE) + creationFlags |= D3D11_CREATE_DEVICE_INSTRUMENTED; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + ThrowIfFailed(D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + 0, + creationFlags, + featureLevels, + _countof(featureLevels), + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + )); + +#ifndef NDEBUG + ComPtr d3dInfoQueue; + if (SUCCEEDED(device.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + ThrowIfFailed(device.As(&m_d3dDevice)); + ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + ThrowIfFailed(m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + m_backBufferFormat, + 0 + )); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + ThrowIfFailed(dxgiAdapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = m_backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGIX_SWAP_CHAIN_FLAG_QUANTIZATION_RGB_FULL; + + // Create a SwapChain from a CoreWindow. + ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + m_swapChain.GetAddressOf() + )); + } + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + ThrowIfFailed(m_swapChain->GetBuffer(0, IID_GRAPHICS_PPV_ARGS(backBuffer.GetAddressOf()))); + + ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = backBufferWidth; + m_outputSize.bottom = backBufferHeight; +} + +// Prepare the render target for rendering. +void DeviceResources::Prepare() +{ +} + +// Present the contents of the swap chain to the screen. +void DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + ThrowIfFailed(m_swapChain->Present(1, 0)); + + // Xbox One apps do not need to handle DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET. +} diff --git a/XDKSamples/Tools/SymbolProxyClient/DeviceResources.h b/XDKSamples/Tools/SymbolProxyClient/DeviceResources.h new file mode 100644 index 0000000000000000000000000000000000000000..b4b7863a7698797182ebbffbf157928b3e61feee --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/DeviceResources.h @@ -0,0 +1,59 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window) { m_window = window; } + void Prepare(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + + // Direct3D Accessors. + ID3D11DeviceX* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContextX* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + + private: + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + RECT m_outputSize; + }; +} \ No newline at end of file diff --git a/XDKSamples/Tools/SymbolProxyClient/Main.cpp b/XDKSamples/Tools/SymbolProxyClient/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ad55bfcbe55986ba84c6dbd35165452508b776e --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/Main.cpp @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Xbox One exclusive title. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SymbolProxyClient.h" + +#include + +#include "Telemetry.h" + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::Foundation; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + // Telemetry Code + if (EventRegisterATGSampleTelemetry() == ERROR_SUCCESS) + { + wchar_t exePath[MAX_PATH+1]; + if (!GetModuleFileNameW(nullptr, exePath, MAX_PATH)) + { + wcscpy_s(exePath, L"Unknown"); + } + EventWriteSampleLoaded(exePath); + } + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + // Default window thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + m_sample->Initialize(reinterpret_cast(window)); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + CoreWindow::GetForCurrentThread()->Activate(); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + +private: + bool m_exit; + std::unique_ptr m_sample; +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + // Default main thread to CPU 0 + SetThreadAffinityMask(GetCurrentThread(), 0x1); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/XDKSamples/Tools/SymbolProxyClient/Package.appxmanifest b/XDKSamples/Tools/SymbolProxyClient/Package.appxmanifest new file mode 100644 index 0000000000000000000000000000000000000000..950b9ab005e0f8979898007510d01bd6c6c612af --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + SymbolProxyClient + Xbox Advanced Technology Group + Assets\StoreLogo.png + SymbolProxyClient + + + + 6.2 + 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDKSamples/Tools/SymbolProxyClient/Readme.docx b/XDKSamples/Tools/SymbolProxyClient/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..bca726cd6221878ab196ead5c3822331ef3b70d6 Binary files /dev/null and b/XDKSamples/Tools/SymbolProxyClient/Readme.docx differ diff --git a/XDKSamples/Tools/SymbolProxyClient/StepTimer.h b/XDKSamples/Tools/SymbolProxyClient/StepTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..f55db2f84a0d3a650d12585056a7aca9368fc581 --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.cpp b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f179fc7c4bbfaa8d2561a429fcfe25ff7e6662c --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.cpp @@ -0,0 +1,414 @@ +//-------------------------------------------------------------------------------------- +// SymbolProxyClient.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SymbolProxyClient.h" +#include + +#include "ATGColors.h" +#include "ControllerFont.h" +#include "CallStack.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +using namespace CallStack; + +Sample::Sample() : + m_frame(0) +{ + m_deviceResources = std::make_unique(); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window) +{ + m_gamePad = std::make_unique(); + + m_deviceResources->SetWindow(window); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + m_backgroundThread = std::thread(&Sample::BackgroundLoop, this); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Frame %I64u", m_frame); + + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); + + PIXEndEvent(); + m_frame++; +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + CaptureRenderThreadCallstack(); + } + if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + CaptureBackgroundThreadCallstackFromRenderThread(); + } + if (m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + LookUpSymbol(); + } + if (m_gamePadButtons.x == GamePad::ButtonStateTracker::PRESSED) + { + m_console->Clear(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the render target to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + // Render the text console + { + m_console->Render(); + } + + // Render the help legend + auto size = m_deviceResources->GetOutputSize(); + auto safe = SimpleMath::Viewport::ComputeTitleSafeArea(size.right, size.bottom); + + m_batch->Begin(); + m_smallFont->DrawString(m_batch.get(), L"Symbol Proxy Client", + XMFLOAT2(float(safe.left), float(safe.top)), ATG::Colors::LightGrey); + + DX::DrawControllerString(m_batch.get(), + m_smallFont.get(), m_ctrlFont.get(), + L"[View] Exit" + L" [A] Capture Callstack on the Render thread" + L" [B] Capture Callstack on the Background thread" + L" [Y] Look up a symbol" + L" [X] Clear the console", + XMFLOAT2(float(safe.left), float(safe.bottom) - m_smallFont->GetLineSpacing()), + ATG::Colors::LightGrey); + + m_batch->End(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(); + PIXEndEvent(context); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetRenderTargetView(); + auto depthStencil = m_deviceResources->GetDepthStencilView(); + + context->ClearRenderTargetView(renderTarget, ATG::Colors::Background); + context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + context->OMSetRenderTargets(1, &renderTarget, depthStencil); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Suspend(0); +} + +void Sample::OnResuming() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->Resume(); + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device, m_deviceResources->GetBackBufferCount()); + + m_console = std::make_unique(context, L"courier_16.spritefont", L"ATGSampleBackground.DDS"); + + m_batch = std::make_unique(context); + m_smallFont = std::make_unique(device, L"SegoeUI_18.spritefont"); + m_ctrlFont = std::make_unique(device, L"XboxOneControllerLegendSmall.spritefont"); +} +#pragma endregion + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + RECT fullscreen = m_deviceResources->GetOutputSize(); + m_console->SetWindow(fullscreen, true); +} + +void Sample::CaptureRenderThreadCallstack() +{ + BackTrace *backtrace = new BackTrace(); + size_t numFrames = backtrace->CaptureCurrentThread(); // As advertised, we are capturing this on the render thread + + // Resolving symbols must make round-trip communications with xbSymbolProxy.exe which isn't particulary fast. + // You wouldn't really want to do this on the render thread and so to demonstrate a best practice we do + // the BackTrace::Resolve call (and subsequent processing) on a new thread. + std::thread([this, backtrace, numFrames]() + { + // backtrace gets cleaned up when uniqueBacktrace goes out of scope + std::unique_ptr uniqueBacktrace(backtrace); + + HRESULT hr = backtrace->Resolve(); + if (FAILED(hr)) + { + m_console->Format(L"[" __FUNCTIONW__ L"] BackTrace::Resolve failed (%0#8x)\n", hr); + DisplayFailureAdvice(hr); + } + + DisplayBacktrace(numFrames, *backtrace); + }).detach(); +} + +void Sample::CaptureBackgroundThreadCallstackFromRenderThread() +{ + HANDLE hBackgroundThread = m_backgroundThread.native_handle(); + BackTrace *backtrace = new BackTrace(); + + // As advertised, we're capturing a callstack of another thread from this thread + size_t numFrames = backtrace->CaptureCrossThread(hBackgroundThread); + + // Since Resolving symbols isn't particularly performant, we do that part (and subsequent processing) + // on a new thread + std::thread([this, backtrace, numFrames]() + { + // backtrace gets cleaned up when uniqueBacktrace goes out of scope + std::unique_ptr uniqueBacktrace(backtrace); + + HRESULT hr = backtrace->Resolve(); + if (FAILED(hr)) + { + m_console->Format(L"[" __FUNCTIONW__ L"] BackTrace::Resolve failed (%0#8x)\n", hr); + DisplayFailureAdvice(hr); + } + + DisplayBacktrace(numFrames, *backtrace); + }).detach(); +} + +void Sample::DisplayBacktrace(size_t numCapturedFrames, const CallStack::BackTrace &backtrace) +{ + if (numCapturedFrames > 0) + { + for (int i = 0; i < backtrace.size(); ++i) + { + const BackTrace::frame_data &fd = backtrace[i]; + if (SUCCEEDED(fd.symbolResult) && SUCCEEDED(fd.sourceResult)) + { + m_console->Format(L"%s + %#x\n", fd.symbolName.c_str(), fd.symbolOffset); + m_console->Format(L"(%s, %i)\n", fd.sourceFileName.c_str(), fd.sourceLineNumber); + } + else if (SUCCEEDED(fd.symbolResult)) + { + m_console->Format(L"%s + %#x\n", fd.symbolName.c_str(), fd.symbolOffset); + } + else + { + m_console->Format(L"%0#16x\n", fd.relativeVirtualAddress + fd.moduleHandle); + } + } + } +} + +void Sample::LookUpSymbol() +{ + // The following two statics are to enable getting the real function address of + // a class member function and then cast it to a void* + static void(__thiscall Sample::*pMember)() = &Sample::Render; + static void *evil = (void*&)pMember; // The compiler won't let you do reinterpret_cast, + // nor will it even allow a c-style cast. Hence the name "evil". + + // A variety of symbols to look up: + static ULONG_PTR symAddresses[] = + { + static_cast(0), // Intentional: this will not resolve to anything + reinterpret_cast(Sample::s_SymCallback), // A static method + reinterpret_cast(evil), // A non-static method + reinterpret_cast(symAddresses) // Not a function or method + }; + + // Incremental Linking Thunk (ILT). Sometimes you will see an address resolves to a symbol like + // the following: + // ILT+16355 (?s_SymCallbackSampleCAHPEAX_KJPEB_WKZ) + // The "ILT" indicates that this ia an Incremental Linking Thunk. It is actually the address of + // a jmp instruction that targets the real function address. (You would probably never see this + // in a callstack since a jmp doesn't push a return address.) + + ULONG_PTR *addresses = symAddresses; + + // Symbol resolution is not performant. Creating a new thread here to avoid stalling the render thread. + std::thread([=]() + { + HRESULT hr = ::GetSymbolFromAddress(ResolveDisposition::DefaultPriority, _countof(symAddresses), addresses, s_SymCallback, this); + if (FAILED(hr)) + { + m_console->Format(L"]" __FUNCTIONW__ L"] GetSymbolFromAddress failed (%0#8x)\n", hr); + } + + if (SUCCEEDED(hr)) + { + hr = ::GetSourceLineFromAddress(ResolveDisposition::DefaultPriority, _countof(symAddresses), addresses, s_SrcCallback, this); + if (FAILED(hr)) + { + m_console->Format(L"[" __FUNCTIONW__ L"] GetSourceLineFromAddress failed (%0#8x)\n", hr); + } + } + + if (FAILED(hr)) + { + DisplayFailureAdvice(hr); + } + }).detach(); +} + +void Sample::DisplayFailureAdvice(HRESULT hr) +{ + if (hr == HRESULT_FROM_WIN32(ERROR_NO_DATA) + || hr == HRESULT_FROM_WIN32(ERROR_INVALID_STATE)) + { + m_console->WriteLine(L": Please start xbSymbolProxy.exe on the development PC and restart the sample."); + } +} + +BOOL Sample::s_SymCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR symName, ULONG offset) +{ + Sample *thisSample = reinterpret_cast(context); + return thisSample->SymCallback(symbolAddress, innerHRESULT, symName, offset); +} + +BOOL Sample::SymCallback(ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR symName, ULONG offset) +{ + if (FAILED(innerHRESULT)) + { + m_console->Format(L"[" __FUNCTIONW__ L"] Not able to resolve symbol for address, %0#16x (HRESULT: %0#8x)\n", symbolAddress, innerHRESULT); + if (innerHRESULT == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + m_console->WriteLine(L"Hint: specify the path to your .pdb folder with SymbolProxy /p "); + } + } + else + { + m_console->Format(L"Resolved symbol name for address %0#16x:\n Name: %s, Offset: %i\n", symbolAddress, symName, offset); + } + return TRUE; +} + +BOOL Sample::s_SrcCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR filepath, ULONG lineNumber) +{ + Sample *thisSample = reinterpret_cast(context); + return thisSample->SrcCallback(symbolAddress, innerHRESULT, filepath, lineNumber); +} + +BOOL Sample::SrcCallback(ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR filepath, ULONG lineNumber) +{ + if (FAILED(innerHRESULT)) + { + m_console->Format(L"[" __FUNCTIONW__ L"] Not able to resolve source information for symbol at address, %0#16x (HRESULT: %0#8x)\n", symbolAddress, innerHRESULT); + } + else + { + m_console->Format(L"Resolved symbol source information for address %0#16x:\n Filepath: %s, Line Number: %i\n", symbolAddress, filepath, lineNumber); + } + return TRUE; +} + +void Sample::BackgroundLoop() +{ + while (true) + { + unsigned maxDepth = 1 + std::rand() % 10; + RecursiveReporter(1, maxDepth); + } +} + +void Sample::RecursiveReporter(unsigned depth, unsigned maxDepth) +{ + if (depth == maxDepth) + { + return; + } + RecursiveReporter(depth + 1, maxDepth); + + { + // The output tells you how many frames to expect when you press the button. + m_console->Format(L"[%s]: depth = %i\n", __FUNCTIONW__, depth); + } + + // This sleep is here to slow it down for the human pressing the button. + Sleep(1000); +} diff --git a/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.h b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.h new file mode 100644 index 0000000000000000000000000000000000000000..53d84aa4d7033e02454c7d4377eb6b89912c0b98 --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.h @@ -0,0 +1,108 @@ +//-------------------------------------------------------------------------------------- +// SymbolProxyClient.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" +#include "TextConsole.h" + +namespace CallStack +{ + class BackTrace; +} + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window); + + // Basic game loop + void Tick(); + + // Messages + void OnSuspending(); + void OnResuming(); + +private: + + void Update(DX::StepTimer const& timer); + void Render(); + + void Clear(); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Capture a callstack on the current thread and display the results to + // the console. Capturing happens on the current thread but symbol + // resolution happens asynchronously on a new thread. + // Note, as the name suggests, this is called from the render thread + void CaptureRenderThreadCallstack(); + + // Capture the callstack for a thread that is not the current thread and + // display the results to the console. After capturing the callstack, + // symbol resolution happens asynchronoulsy on a new thread. + void CaptureBackgroundThreadCallstackFromRenderThread(); + + // Helper function to display a callstack to the console. + void DisplayBacktrace(size_t numCapturedFrames, const CallStack::BackTrace &backtrace); + + // Send some symbols to the symbol proxy and then display the results to the + // console. + void LookUpSymbol(); + + // Helper to display diagnostics to the console in case there is a failure. + void DisplayFailureAdvice(HRESULT hr); + + // The sample has an option to demonstrate capturing a callstack on a background + // thread. The background thread runs in a loop and prints messages to the console. + void BackgroundLoop(); + + // Background loop calls this function with a depth value. The function then + // increments the value and recursively calls itself. This allows the user to + // capture callstacks of varying depths depending on how deep the recursion is. + void RecursiveReporter(unsigned depth, unsigned maxDepth); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + uint64_t m_frame; + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + + // Text Conosole + std::unique_ptr m_console; + + // Background Thread + std::thread m_backgroundThread; + + // Help Legend + std::unique_ptr m_batch; + std::unique_ptr m_smallFont; + std::unique_ptr m_ctrlFont; + + static BOOL CALLBACK s_SymCallback(LPVOID context, ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR symName, ULONG offset); + BOOL SymCallback(ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR symName, ULONG offset); + + static BOOL CALLBACK s_SrcCallback( LPVOID context, ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR filepath, ULONG lineNumber); + BOOL SrcCallback(ULONG_PTR symbolAddress, HRESULT innerHRESULT, PCWSTR filepath, ULONG lineNumber); +}; diff --git a/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.sln b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.sln new file mode 100644 index 0000000000000000000000000000000000000000..aeb921a69fdf6779f641963b9974f51726c951c2 --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SymbolProxyClient", "SymbolProxyClient.vcxproj", "{A0189E04-7CA4-4B17-AA91-3E0E001410D4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK_XboxOneXDK_2015", "..\..\..\Kits\DirectXTK\DirectXTK_XboxOneXDK_2015.vcxproj", "{4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Durango = Debug|Durango + Profile|Durango = Profile|Durango + Release|Durango = Release|Durango + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Debug|Durango.ActiveCfg = Debug|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Debug|Durango.Build.0 = Debug|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Debug|Durango.Deploy.0 = Debug|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Profile|Durango.ActiveCfg = Profile|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Profile|Durango.Build.0 = Profile|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Profile|Durango.Deploy.0 = Profile|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Release|Durango.ActiveCfg = Release|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Release|Durango.Build.0 = Release|Durango + {A0189E04-7CA4-4B17-AA91-3E0E001410D4}.Release|Durango.Deploy.0 = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.ActiveCfg = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Debug|Durango.Build.0 = Debug|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.ActiveCfg = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Profile|Durango.Build.0 = Profile|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.ActiveCfg = Release|Durango + {4FDFDCCD-EE2E-415C-B458-1E8FDB0D85F2}.Release|Durango.Build.0 = Release|Durango + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.vcxproj b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..48308ce5b6464b31b1988c95aafc3424e0aaa84e --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.vcxproj @@ -0,0 +1,231 @@ + + + + + Release + Durango + + + Profile + Durango + + + Debug + Durango + + + + SymbolProxyClient + {a0189e04-7ca4-4b17-aa91-3e0e001410d4} + en-US + Win32Proj + title + + v140 + 14.0 + Native + + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + false + true + Unicode + false + false + + + Application + v140 + true + Unicode + false + false + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(VCInstallDir)bin\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH); + true + + + + d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies);toolhelpx.lib + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\CPUTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies);toolhelpx.lib + + + true + Windows + true + true + false + + + Use + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\CPUTK;%(AdditionalIncludeDirectories) + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + MaxSpeed + NDEBUG;__WRL_NO_DEFAULT_LIB__;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + + + 5.0 + true + /Qstrip_debug /Fd"$(OutDir)%(Filename).pdb" %(AdditionalOptions) + + + + + pixEvt.lib;d3d11_x.lib;combase.lib;kernelx.lib;uuid.lib;etwplus.lib;$(XboxExtensionsDependencies);toolhelpx.lib + Windows + true + false + + + pch.h + ..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;..\..\..\Kits\CPUTK;%(AdditionalIncludeDirectories) + Use + false + $(Console_SdkPackagesRoot);$(Console_SdkWindowsMetadataPath);%(AdditionalUsingDirectories) + Level4 + Disabled + _DEBUG;__WRL_NO_DEFAULT_LIB__;%(PreprocessorDefinitions) + + + 5.0 + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + {4fdfdccd-ee2e-415c-b458-1e8fdb0d85f2} + + + + + true + true + true + + + true + true + true + + + true + true + true + + + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.vcxproj.filters b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..bbda7a606b22c2f5568a36c3a335de4fa31d391a --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/SymbolProxyClient.vcxproj.filters @@ -0,0 +1,94 @@ + + + + + bcf8227c-af8e-4afb-a5e6-5732c84b9eee + + + c40ab8c2-14d3-4e81-9845-8501f6111e0e + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {b7732cd6-f101-4907-8c33-3aada9955c9c} + + + {5e417e74-fe52-45bb-bd61-346d951281ca} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + + ATG Tool Kit + + + ATG Tool Kit + + + ATG CPU Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + ATG Tool Kit + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + Assets + + + Assets + + + Assets + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/SymbolProxyClient/Telemetry.h b/XDKSamples/Tools/SymbolProxyClient/Telemetry.h new file mode 100644 index 0000000000000000000000000000000000000000..da34a808edbd12e714b9b6842bab34ec6e45fa43 --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/Telemetry.h @@ -0,0 +1,92 @@ + +//**********************************************************************` +//* This is an include file generated by EtwPlusTool. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once +#pragma pack(push, 16) + +#include "EtwPlus.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Field Descriptors, used in the ETX_EVENT_DESCRIPTOR array below +// +EXTERN_C __declspec(selectany) ETX_FIELD_DESCRIPTOR ATGSampleTelemetry_SampleLoaded_Fields[2] = {{EtxFieldType_UnicodeString,0},{EtxFieldType_UnicodeString,0}}; + +// Event name mapping +// +#define SampleLoaded_value 1 + +// Event Descriptor array +// +EXTERN_C __declspec(selectany) ETX_EVENT_DESCRIPTOR ATGSampleTelemetryEvents[1] = { + {{ 1, 1, 0, 0, 0, 0, 0x0 }, "SampleLoaded", "0.7.0.1", ATGSampleTelemetry_SampleLoaded_Fields, 2, 0, EtxEventEnabledState_Undefined, EtxEventEnabledState_ProviderDefault, EtxPopulationSample_Undefined, 100, EtxEventLatency_Undefined, EtxEventLatency_ProviderDefault, EtxEventPriority_Undefined, EtxEventPriority_ProviderDefault }}; + +// Provider Descriptor for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) ETX_PROVIDER_DESCRIPTOR ATGSampleTelemetryProvider = {"ATGSampleTelemetry", {0x1d9d44d6,0x4b94,0x4b72,{0xa8,0xa4,0xda,0x77,0xe0,0x50,0x9e,0xbb}}, 1, (ETX_EVENT_DESCRIPTOR*)&ATGSampleTelemetryEvents, 0, EtxProviderEnabledState_Undefined, EtxProviderEnabledState_OnByDefault, 0, 100, EtxProviderLatency_Undefined, EtxProviderLatency_Normal, EtxProviderPriority_Undefined, EtxProviderPriority_Normal}; + +// ETW handle for ATGSampleTelemetry +// +EXTERN_C __declspec(selectany) REGHANDLE ATGSampleTelemetryHandle = (REGHANDLE)0; + +/*++ + +Routine Description: + + Register the provider with ETW+. + +Arguments: + + None + +Remarks: + + ERROR_SUCCESS if success or if the provider was already registered. + Otherwise, an error code. + +--*/ +#define EventRegisterATGSampleTelemetry() EtxRegister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +/*++ + +Routine Description: + + Unregister the provider from ETW+. + +Arguments: + None +Remarks: + ERROR_SUCCESS if success or if the provider was not registered. + Otherwise, an error code. +--*/ +#define EventUnregisterATGSampleTelemetry() EtxUnregister(&ATGSampleTelemetryProvider, &ATGSampleTelemetryHandle) + +#define EventEnabledSampleLoaded() (TRUE) + +// Entry point to log the event SampleLoaded +// +__inline +ULONG +EventWriteSampleLoaded(__in_opt PCWSTR ExeName) +{ +#define ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded 2 + + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded]; + UINT8 scratch[64]; + + EtxFillCommonFields_v7(&EventData[0], scratch, 64); + + EventDataDescCreate(&EventData[1], (ExeName != NULL) ? ExeName : L"", (ExeName != NULL) ? (ULONG)((wcslen(ExeName) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"")); + + return EtxEventWrite(&ATGSampleTelemetryEvents[0], &ATGSampleTelemetryProvider, ATGSampleTelemetryHandle, ARGUMENT_COUNT_ATGSampleTelemetry_SampleLoaded, EventData); +} +#if defined(__cplusplus) +}; +#endif + +#pragma pack(pop) diff --git a/XDKSamples/Tools/SymbolProxyClient/pch.cpp b/XDKSamples/Tools/SymbolProxyClient/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb58e7034dc7de85a9d67168054f28b543c63a1a --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/XDKSamples/Tools/SymbolProxyClient/pch.h b/XDKSamples/Tools/SymbolProxyClient/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..7adba383f7256ef0c6f37cb41681be75052fa8bf --- /dev/null +++ b/XDKSamples/Tools/SymbolProxyClient/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#if _XDK_VER < 0x38100402 /* XDK Edition: 160600 */ +#error This sample requires the June 2016 XDK (Preview) or later +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/XDKSamples/Tools/xtexconv/DirectXTexEXR.cpp b/XDKSamples/Tools/xtexconv/DirectXTexEXR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76129ba680efe4fb1bb85c91320c4c83405e59d0 --- /dev/null +++ b/XDKSamples/Tools/xtexconv/DirectXTexEXR.cpp @@ -0,0 +1,521 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexEXR.cpp +// +// DirectXTex Auxillary functions for using the OpenEXR library +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +//Uncomment if you add DirectXTexEXR to your copy of the DirectXTex library +//#include "DirectXTexp.h" + +#include "DirectXTexEXR.h" + +#include + +#include +#include +#include + +// +// Requires the OpenEXR library and ZLIB +// + +#pragma warning(push) +#pragma warning(disable : 4244 4996) +#include +#include +#pragma warning(pop) + +static_assert(sizeof(Imf::Rgba) == 8, "Mismatch size"); + +using namespace DirectX; +using PackedVector::XMHALF4; + +// Comment out this first anonymous namespace if you add the include of DirectXTexP.h above +namespace +{ + struct handle_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) CloseHandle(h); } }; + + typedef public std::unique_ptr ScopedHandle; + + inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } + + class auto_delete_file + { + public: + auto_delete_file(HANDLE hFile) : m_handle(hFile) {} + + auto_delete_file(const auto_delete_file&) = delete; + auto_delete_file& operator=(const auto_delete_file&) = delete; + + ~auto_delete_file() + { + if (m_handle) + { + FILE_DISPOSITION_INFO info = { 0 }; + info.DeleteFile = TRUE; + (void)SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, sizeof(info)); + } + } + + void clear() { m_handle = 0; } + + private: + HANDLE m_handle; + }; +} + +namespace +{ + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = {}; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + HRESULT hr() const { return result; } + + private: + HRESULT result; + }; + + class InputStream : public Imf::IStream + { + public: + InputStream(HANDLE hFile, const char fileName[]) : + IStream(fileName), m_hFile(hFile) + { + LARGE_INTEGER dist = { 0 }; + LARGE_INTEGER result; + if (!SetFilePointerEx(m_hFile, dist, &result, FILE_END)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + + m_EOF = result.QuadPart; + + if (!SetFilePointerEx(m_hFile, dist, nullptr, FILE_BEGIN)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + } + + InputStream(const InputStream &) = delete; + InputStream& operator = (const InputStream &) = delete; + + virtual bool read(char c[], int n) override + { + DWORD bytesRead; + if (!ReadFile(m_hFile, c, static_cast(n), &bytesRead, nullptr)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + + LARGE_INTEGER dist = { 0 }; + LARGE_INTEGER result; + if (!SetFilePointerEx(m_hFile, dist, &result, FILE_CURRENT)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + + return result.QuadPart >= m_EOF; + } + + virtual Imf::Int64 tellg() override + { + LARGE_INTEGER dist = { 0 }; + LARGE_INTEGER result; + if (!SetFilePointerEx(m_hFile, dist, &result, FILE_CURRENT)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + return result.QuadPart; + } + + virtual void seekg(Imf::Int64 pos) override + { + LARGE_INTEGER dist; + dist.QuadPart = pos; + if (!SetFilePointerEx(m_hFile, dist, nullptr, FILE_BEGIN)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + } + + virtual void clear() override + { + SetLastError(0); + } + + private: + HANDLE m_hFile; + LONGLONG m_EOF; + }; + + class OutputStream : public Imf::OStream + { + public: + OutputStream(HANDLE hFile, const char fileName[]) : + OStream(fileName), m_hFile(hFile) {} + + OutputStream(const OutputStream &) = delete; + OutputStream& operator = (const OutputStream &) = delete; + + virtual void write(const char c[], int n) override + { + DWORD bytesWritten; + if (!WriteFile(m_hFile, c, static_cast(n), &bytesWritten, nullptr)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + } + + virtual Imf::Int64 tellp() override + { + LARGE_INTEGER dist = { 0 }; + LARGE_INTEGER result; + if (!SetFilePointerEx(m_hFile, dist, &result, FILE_CURRENT)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + return result.QuadPart; + } + + virtual void seekp(Imf::Int64 pos) override + { + LARGE_INTEGER dist; + dist.QuadPart = pos; + if (!SetFilePointerEx(m_hFile, dist, nullptr, FILE_BEGIN)) + { + throw com_exception(HRESULT_FROM_WIN32(GetLastError())); + } + } + + private: + HANDLE m_hFile; + }; +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Obtain metadata from EXR file on disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::GetMetadataFromEXRFile(const wchar_t* szFile, TexMetadata& metadata) +{ + if (!szFile) + return E_INVALIDARG; + + char fileName[MAX_PATH]; + int result = WideCharToMultiByte(CP_ACP, 0, szFile, -1, fileName, MAX_PATH, nullptr, nullptr); + if (result <= 0) + { + *fileName = 0; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + InputStream stream(hFile.get(), fileName); + + HRESULT hr = S_OK; + + try + { + Imf::RgbaInputFile file(stream); + + auto dw = file.dataWindow(); + + int width = dw.max.x - dw.min.x + 1; + int height = dw.max.y - dw.min.y + 1; + + if (width < 1 || height < 1) + return E_FAIL; + + metadata.width = static_cast(width); + metadata.height = static_cast(height); + metadata.depth = metadata.arraySize = metadata.mipLevels = 1; + metadata.format = DXGI_FORMAT_R16G16B16A16_FLOAT; + metadata.dimension = TEX_DIMENSION_TEXTURE2D; + } + catch (const com_exception& exc) + { +#ifdef _DEBUG + OutputDebugStringA(exc.what()); +#endif + hr = exc.hr(); + } + catch (const std::exception& exc) + { + exc; +#ifdef _DEBUG + OutputDebugStringA(exc.what()); +#endif + hr = E_FAIL; + } + catch (...) + { + hr = E_UNEXPECTED; + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Load a EXR file from disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, ScratchImage& image) +{ + if (!szFile) + return E_INVALIDARG; + + image.Release(); + + if (metadata) + { + memset(metadata, 0, sizeof(TexMetadata)); + } + + char fileName[MAX_PATH]; + int result = WideCharToMultiByte(CP_ACP, 0, szFile, -1, fileName, MAX_PATH, nullptr, nullptr); + if (result <= 0) + { + *fileName = 0; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + InputStream stream(hFile.get(), fileName); + + HRESULT hr = S_OK; + + try + { + Imf::RgbaInputFile file(stream); + + auto dw = file.dataWindow(); + + int width = dw.max.x - dw.min.x + 1; + int height = dw.max.y - dw.min.y + 1; + + if (width < 1 || height < 1) + return E_FAIL; + + if (metadata) + { + metadata->width = static_cast(width); + metadata->height = static_cast(height); + metadata->depth = metadata->arraySize = metadata->mipLevels = 1; + metadata->format = DXGI_FORMAT_R16G16B16A16_FLOAT; + metadata->dimension = TEX_DIMENSION_TEXTURE2D; + } + + hr = image.Initialize2D(DXGI_FORMAT_R16G16B16A16_FLOAT, width, height, 1, 1); + if (FAILED(hr)) + return hr; + + file.setFrameBuffer(reinterpret_cast(image.GetPixels()) - dw.min.x - dw.min.y * width, 1, width); + file.readPixels(dw.min.y, dw.max.y); + } + catch (const com_exception& exc) + { +#ifdef _DEBUG + OutputDebugStringA(exc.what()); +#endif + hr = exc.hr(); + } + catch (const std::exception& exc) + { + exc; +#ifdef _DEBUG + OutputDebugStringA(exc.what()); +#endif + hr = E_FAIL; + } + catch (...) + { + hr = E_UNEXPECTED; + } + + if (FAILED(hr)) + { + image.Release(); + } + + return hr; +} + + +//------------------------------------------------------------------------------------- +// Save a EXR file to disk +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveToEXRFile(const Image& image, const wchar_t* szFile) +{ + if (!szFile) + return E_INVALIDARG; + + if (!image.pixels) + return E_POINTER; + + if (image.width > INT32_MAX || image.height > INT32_MAX) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + switch (image.format) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + if ((image.rowPitch % 8) > 0) + return E_FAIL; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32_FLOAT: + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + char fileName[MAX_PATH]; + int result = WideCharToMultiByte(CP_ACP, 0, szFile, -1, fileName, MAX_PATH, nullptr, nullptr); + if (result <= 0) + { + *fileName = 0; + } + // Create file and write header +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(szFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr))); +#endif + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + auto_delete_file delonfail(hFile.get()); + + OutputStream stream(hFile.get(), fileName); + + HRESULT hr = S_OK; + + try + { + int width = static_cast(image.width); + int height = static_cast(image.height); + + Imf::RgbaOutputFile file(stream, Imf::Header(width, height), Imf::WRITE_RGBA); + + if (image.format == DXGI_FORMAT_R16G16B16A16_FLOAT) + { + file.setFrameBuffer(reinterpret_cast(image.pixels), 1, image.rowPitch / 8); + file.writePixels(height); + } + else + { + std::unique_ptr temp(new (std::nothrow) XMHALF4[width * height]); + if (!temp) + return E_OUTOFMEMORY; + + file.setFrameBuffer(reinterpret_cast(temp.get()), 1, width); + + auto sPtr = image.pixels; + auto dPtr = temp.get(); + if (image.format == DXGI_FORMAT_R32G32B32A32_FLOAT) + { + for (int j = 0; j < height; ++j) + { + auto srcPtr = reinterpret_cast(sPtr); + auto destPtr = dPtr; + for (int k = 0; k < width; ++k, ++srcPtr, ++destPtr) + { + XMVECTOR v = XMLoadFloat4(srcPtr); + PackedVector::XMStoreHalf4(destPtr, v); + } + + sPtr += image.rowPitch; + dPtr += width; + + file.writePixels(1); + } + } + else + { + assert(image.format == DXGI_FORMAT_R32G32B32_FLOAT); + + for (int j = 0; j < height; ++j) + { + auto srcPtr = reinterpret_cast(sPtr); + auto destPtr = dPtr; + for (int k = 0; k < width; ++k, ++srcPtr, ++destPtr) + { + XMVECTOR v = XMLoadFloat3(srcPtr); + v = XMVectorSelect(g_XMIdentityR3, v, g_XMSelect1110); + PackedVector::XMStoreHalf4(destPtr, v); + } + + sPtr += image.rowPitch; + dPtr += width; + + file.writePixels(1); + } + } + } + } + catch (const com_exception& exc) + { +#ifdef _DEBUG + OutputDebugStringA(exc.what()); +#endif + hr = exc.hr(); + } + catch (const std::exception& exc) + { + exc; +#ifdef _DEBUG + OutputDebugStringA(exc.what()); +#endif + hr = E_FAIL; + } + catch (...) + { + hr = E_UNEXPECTED; + } + + if (FAILED(hr)) + return hr; + + delonfail.clear(); + + return S_OK; +} diff --git a/XDKSamples/Tools/xtexconv/DirectXTexEXR.h b/XDKSamples/Tools/xtexconv/DirectXTexEXR.h new file mode 100644 index 0000000000000000000000000000000000000000..c403c1fc462c297ca872e7ff1a8eb4a8a83ed9cd --- /dev/null +++ b/XDKSamples/Tools/xtexconv/DirectXTexEXR.h @@ -0,0 +1,22 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXTexEXR.h +// +// DirectXTex Auxillary functions for using the OpenEXR library +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "directxtex.h" + +#pragma comment(lib,"IlmImf-2_2.lib") + +namespace DirectX +{ + HRESULT __cdecl GetMetadataFromEXRFile( _In_z_ const wchar_t* szFile, + _Out_ TexMetadata& metadata ); + + HRESULT __cdecl LoadFromEXRFile( _In_z_ const wchar_t* szFile, + _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image ); + + HRESULT __cdecl SaveToEXRFile( _In_ const Image& image, _In_z_ const wchar_t* szFile ); +}; diff --git a/XDKSamples/Tools/xtexconv/Readme.docx b/XDKSamples/Tools/xtexconv/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..99b804789f22e4b374fd91d7115eb50ac6c811d9 Binary files /dev/null and b/XDKSamples/Tools/xtexconv/Readme.docx differ diff --git a/XDKSamples/Tools/xtexconv/packages.config b/XDKSamples/Tools/xtexconv/packages.config new file mode 100644 index 0000000000000000000000000000000000000000..68b3fb2f5d3e2596622c4db45948d3d44a1ce83f --- /dev/null +++ b/XDKSamples/Tools/xtexconv/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/xtexconv/texconv.cpp b/XDKSamples/Tools/xtexconv/texconv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..388da1bd4dd4769fd49f3e8e1c46e69ae61f0345 --- /dev/null +++ b/XDKSamples/Tools/xtexconv/texconv.cpp @@ -0,0 +1,2561 @@ +//-------------------------------------------------------------------------------------- +// File: TexConv.cpp +// +// DirectX Texture Converter for Xbox One +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#ifndef _M_X64 +#error This tool is only supported for x64 native +#endif + +#pragma warning(push) +#pragma warning(disable : 4005) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NODRAWTEXT +#define NOGDI +#define NOBITMAP +#define NOMCX +#define NOSERVICE +#define NOHELP +#pragma warning(pop) + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include "directxtex.h" +#include "DirectXTexXbox.h" + +#include "DirectXPackedVector.h" + +#include +#include + +//Comment to remove support for OpenEXR (.exr) +#define USE_OPENEXR + +#ifdef USE_OPENEXR +// See for details +#include "DirectXTexEXR.h" +#endif + +using namespace DirectX; +using namespace DirectX::PackedVector; +using Microsoft::WRL::ComPtr; + +enum OPTIONS +{ + OPT_RECURSIVE = 1, + OPT_WIDTH, + OPT_HEIGHT, + OPT_MIPLEVELS, + OPT_FORMAT, + OPT_FILTER, + OPT_SRGBI, + OPT_SRGBO, + OPT_SRGB, + OPT_PREFIX, + OPT_SUFFIX, + OPT_OUTPUTDIR, + OPT_OVERWRITE, + OPT_FILETYPE, + OPT_HFLIP, + OPT_VFLIP, + OPT_DDS_DWORD_ALIGN, + OPT_DDS_BAD_DXTN_TAILS, + OPT_USE_DX10, + OPT_NOLOGO, + OPT_TIMING, + OPT_SEPALPHA, + OPT_TYPELESS_UNORM, + OPT_TYPELESS_FLOAT, + OPT_PREMUL_ALPHA, + OPT_DEMUL_ALPHA, + OPT_EXPAND_LUMINANCE, + OPT_TA_WRAP, + OPT_TA_MIRROR, + OPT_FORCE_SINGLEPROC, + OPT_GPU, + OPT_NOGPU, + OPT_FEATURE_LEVEL, + OPT_FIT_POWEROF2, + OPT_ALPHA_WEIGHT, + OPT_NORMAL_MAP, + OPT_NORMAL_MAP_AMPLITUDE, + OPT_COMPRESS_UNIFORM, + OPT_COMPRESS_MAX, + OPT_COMPRESS_QUICK, + OPT_COMPRESS_DITHER, + OPT_WIC_QUALITY, + OPT_WIC_LOSSLESS, + OPT_WIC_MULTIFRAME, + OPT_COLORKEY, + OPT_TONEMAP, + OPT_X2_BIAS, + OPT_FILELIST, + OPT_USE_XBOX, + OPT_XGMODE, + OPT_MAX +}; + +static_assert(OPT_MAX <= 64, "dwOptions is a DWORD64 bitfield"); + +struct SConversion +{ + wchar_t szSrc[MAX_PATH]; + wchar_t szDest[MAX_PATH]; +}; + +struct SValue +{ + LPCWSTR pName; + DWORD dwValue; +}; + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +const SValue g_pOptions[] = +{ + { L"r", OPT_RECURSIVE }, + { L"w", OPT_WIDTH }, + { L"h", OPT_HEIGHT }, + { L"m", OPT_MIPLEVELS }, + { L"f", OPT_FORMAT }, + { L"if", OPT_FILTER }, + { L"srgbi", OPT_SRGBI }, + { L"srgbo", OPT_SRGBO }, + { L"srgb", OPT_SRGB }, + { L"px", OPT_PREFIX }, + { L"sx", OPT_SUFFIX }, + { L"o", OPT_OUTPUTDIR }, + { L"y", OPT_OVERWRITE }, + { L"ft", OPT_FILETYPE }, + { L"hflip", OPT_HFLIP }, + { L"vflip", OPT_VFLIP }, + { L"dword", OPT_DDS_DWORD_ALIGN }, + { L"badtails", OPT_DDS_BAD_DXTN_TAILS }, + { L"dx10", OPT_USE_DX10 }, + { L"nologo", OPT_NOLOGO }, + { L"timing", OPT_TIMING }, + { L"sepalpha", OPT_SEPALPHA }, + { L"tu", OPT_TYPELESS_UNORM }, + { L"tf", OPT_TYPELESS_FLOAT }, + { L"pmalpha", OPT_PREMUL_ALPHA }, + { L"alpha", OPT_DEMUL_ALPHA }, + { L"xlum", OPT_EXPAND_LUMINANCE }, + { L"wrap", OPT_TA_WRAP }, + { L"mirror", OPT_TA_MIRROR }, + { L"singleproc", OPT_FORCE_SINGLEPROC }, + { L"gpu", OPT_GPU }, + { L"nogpu", OPT_NOGPU }, + { L"fl", OPT_FEATURE_LEVEL }, + { L"pow2", OPT_FIT_POWEROF2 }, + { L"aw", OPT_ALPHA_WEIGHT }, + { L"nmap", OPT_NORMAL_MAP }, + { L"nmapamp", OPT_NORMAL_MAP_AMPLITUDE }, + { L"bcuniform", OPT_COMPRESS_UNIFORM }, + { L"bcmax", OPT_COMPRESS_MAX }, + { L"bcquick", OPT_COMPRESS_QUICK }, + { L"bcdither", OPT_COMPRESS_DITHER }, + { L"wicq", OPT_WIC_QUALITY }, + { L"wiclossless", OPT_WIC_LOSSLESS }, + { L"wicmulti", OPT_WIC_MULTIFRAME }, + { L"c", OPT_COLORKEY }, + { L"tonemap", OPT_TONEMAP }, + { L"x2bias", OPT_X2_BIAS }, + { L"flist", OPT_FILELIST }, + { L"xbox", OPT_USE_XBOX }, + { L"xgmode", OPT_XGMODE }, + { nullptr, 0 } +}; + +#define DEFFMT(fmt) { L#fmt, DXGI_FORMAT_ ## fmt } + +const SValue g_pFormats[] = +{ + // List does not include _TYPELESS or depth/stencil formats + DEFFMT(R32G32B32A32_FLOAT), + DEFFMT(R32G32B32A32_UINT), + DEFFMT(R32G32B32A32_SINT), + DEFFMT(R32G32B32_FLOAT), + DEFFMT(R32G32B32_UINT), + DEFFMT(R32G32B32_SINT), + DEFFMT(R16G16B16A16_FLOAT), + DEFFMT(R16G16B16A16_UNORM), + DEFFMT(R16G16B16A16_UINT), + DEFFMT(R16G16B16A16_SNORM), + DEFFMT(R16G16B16A16_SINT), + DEFFMT(R32G32_FLOAT), + DEFFMT(R32G32_UINT), + DEFFMT(R32G32_SINT), + DEFFMT(R10G10B10A2_UNORM), + DEFFMT(R10G10B10A2_UINT), + DEFFMT(R11G11B10_FLOAT), + DEFFMT(R8G8B8A8_UNORM), + DEFFMT(R8G8B8A8_UNORM_SRGB), + DEFFMT(R8G8B8A8_UINT), + DEFFMT(R8G8B8A8_SNORM), + DEFFMT(R8G8B8A8_SINT), + DEFFMT(R16G16_FLOAT), + DEFFMT(R16G16_UNORM), + DEFFMT(R16G16_UINT), + DEFFMT(R16G16_SNORM), + DEFFMT(R16G16_SINT), + DEFFMT(R32_FLOAT), + DEFFMT(R32_UINT), + DEFFMT(R32_SINT), + DEFFMT(R8G8_UNORM), + DEFFMT(R8G8_UINT), + DEFFMT(R8G8_SNORM), + DEFFMT(R8G8_SINT), + DEFFMT(R16_FLOAT), + DEFFMT(R16_UNORM), + DEFFMT(R16_UINT), + DEFFMT(R16_SNORM), + DEFFMT(R16_SINT), + DEFFMT(R8_UNORM), + DEFFMT(R8_UINT), + DEFFMT(R8_SNORM), + DEFFMT(R8_SINT), + DEFFMT(A8_UNORM), + DEFFMT(R9G9B9E5_SHAREDEXP), + DEFFMT(R8G8_B8G8_UNORM), + DEFFMT(G8R8_G8B8_UNORM), + DEFFMT(BC1_UNORM), + DEFFMT(BC1_UNORM_SRGB), + DEFFMT(BC2_UNORM), + DEFFMT(BC2_UNORM_SRGB), + DEFFMT(BC3_UNORM), + DEFFMT(BC3_UNORM_SRGB), + DEFFMT(BC4_UNORM), + DEFFMT(BC4_SNORM), + DEFFMT(BC5_UNORM), + DEFFMT(BC5_SNORM), + DEFFMT(B5G6R5_UNORM), + DEFFMT(B5G5R5A1_UNORM), + + // DXGI 1.1 formats + DEFFMT(B8G8R8A8_UNORM), + DEFFMT(B8G8R8X8_UNORM), + DEFFMT(R10G10B10_XR_BIAS_A2_UNORM), + DEFFMT(B8G8R8A8_UNORM_SRGB), + DEFFMT(B8G8R8X8_UNORM_SRGB), + DEFFMT(BC6H_UF16), + DEFFMT(BC6H_SF16), + DEFFMT(BC7_UNORM), + DEFFMT(BC7_UNORM_SRGB), + + // DXGI 1.2 formats + DEFFMT(AYUV), + DEFFMT(Y410), + DEFFMT(Y416), + DEFFMT(YUY2), + DEFFMT(Y210), + DEFFMT(Y216), + // No support for legacy paletted video formats (AI44, IA44, P8, A8P8) + DEFFMT(B4G4R4A4_UNORM), + + // Xbox One extended formats + { L"R10G10B10_7E3_A2_FLOAT", DXGI_FORMAT(116) }, + { L"R10G10B10_6E4_A2_FLOAT", DXGI_FORMAT(117) }, + { L"R10G10B10_SNORM_A2_UNORM", DXGI_FORMAT(189) }, + { L"R4G4_UNORM", DXGI_FORMAT(190) }, + + { nullptr, DXGI_FORMAT_UNKNOWN } +}; + +const SValue g_pReadOnlyFormats[] = +{ + DEFFMT(R32G32B32A32_TYPELESS), + DEFFMT(R32G32B32_TYPELESS), + DEFFMT(R16G16B16A16_TYPELESS), + DEFFMT(R32G32_TYPELESS), + DEFFMT(R32G8X24_TYPELESS), + DEFFMT(D32_FLOAT_S8X24_UINT), + DEFFMT(R32_FLOAT_X8X24_TYPELESS), + DEFFMT(X32_TYPELESS_G8X24_UINT), + DEFFMT(R10G10B10A2_TYPELESS), + DEFFMT(R8G8B8A8_TYPELESS), + DEFFMT(R16G16_TYPELESS), + DEFFMT(R32_TYPELESS), + DEFFMT(D32_FLOAT), + DEFFMT(R24G8_TYPELESS), + DEFFMT(D24_UNORM_S8_UINT), + DEFFMT(R24_UNORM_X8_TYPELESS), + DEFFMT(X24_TYPELESS_G8_UINT), + DEFFMT(R8G8_TYPELESS), + DEFFMT(R16_TYPELESS), + DEFFMT(R8_TYPELESS), + DEFFMT(BC1_TYPELESS), + DEFFMT(BC2_TYPELESS), + DEFFMT(BC3_TYPELESS), + DEFFMT(BC4_TYPELESS), + DEFFMT(BC5_TYPELESS), + + // DXGI 1.1 formats + DEFFMT(B8G8R8A8_TYPELESS), + DEFFMT(B8G8R8X8_TYPELESS), + DEFFMT(BC6H_TYPELESS), + DEFFMT(BC7_TYPELESS), + + // DXGI 1.2 formats + DEFFMT(NV12), + DEFFMT(P010), + DEFFMT(P016), + DEFFMT(420_OPAQUE), + DEFFMT(NV11), + + // DXGI 1.3 formats + { L"P208", DXGI_FORMAT(130) }, + { L"V208", DXGI_FORMAT(131) }, + { L"V408", DXGI_FORMAT(132) }, + + // Xbox One extended formats + { L"D16_UNORM_S8_UINT", DXGI_FORMAT(118) }, + { L"R16_UNORM_X8_TYPELESS", DXGI_FORMAT(119) }, + { L"X16_TYPELESS_G8_UINT", DXGI_FORMAT(120) }, + + { nullptr, DXGI_FORMAT_UNKNOWN } +}; + +const SValue g_pFilters[] = +{ + { L"POINT", TEX_FILTER_POINT }, + { L"LINEAR", TEX_FILTER_LINEAR }, + { L"CUBIC", TEX_FILTER_CUBIC }, + { L"FANT", TEX_FILTER_FANT }, + { L"BOX", TEX_FILTER_BOX }, + { L"TRIANGLE", TEX_FILTER_TRIANGLE }, + { L"POINT_DITHER", TEX_FILTER_POINT | TEX_FILTER_DITHER }, + { L"LINEAR_DITHER", TEX_FILTER_LINEAR | TEX_FILTER_DITHER }, + { L"CUBIC_DITHER", TEX_FILTER_CUBIC | TEX_FILTER_DITHER }, + { L"FANT_DITHER", TEX_FILTER_FANT | TEX_FILTER_DITHER }, + { L"BOX_DITHER", TEX_FILTER_BOX | TEX_FILTER_DITHER }, + { L"TRIANGLE_DITHER", TEX_FILTER_TRIANGLE | TEX_FILTER_DITHER }, + { L"POINT_DITHER_DIFFUSION", TEX_FILTER_POINT | TEX_FILTER_DITHER_DIFFUSION }, + { L"LINEAR_DITHER_DIFFUSION", TEX_FILTER_LINEAR | TEX_FILTER_DITHER_DIFFUSION }, + { L"CUBIC_DITHER_DIFFUSION", TEX_FILTER_CUBIC | TEX_FILTER_DITHER_DIFFUSION }, + { L"FANT_DITHER_DIFFUSION", TEX_FILTER_FANT | TEX_FILTER_DITHER_DIFFUSION }, + { L"BOX_DITHER_DIFFUSION", TEX_FILTER_BOX | TEX_FILTER_DITHER_DIFFUSION }, + { L"TRIANGLE_DITHER_DIFFUSION", TEX_FILTER_TRIANGLE | TEX_FILTER_DITHER_DIFFUSION }, + { nullptr, TEX_FILTER_DEFAULT } +}; + +#define CODEC_DDS 0xFFFF0001 +#define CODEC_TGA 0xFFFF0002 +#define CODEC_HDP 0xFFFF0003 +#define CODEC_JXR 0xFFFF0004 +#define CODEC_HDR 0xFFFF0005 +#define CODEC_EXR 0xFFFF0006 + +const SValue g_pSaveFileTypes[] = // valid formats to write to +{ + { L"BMP", WIC_CODEC_BMP }, + { L"JPG", WIC_CODEC_JPEG }, + { L"JPEG", WIC_CODEC_JPEG }, + { L"PNG", WIC_CODEC_PNG }, + { L"DDS", CODEC_DDS }, + { L"TGA", CODEC_TGA }, + { L"HDR", CODEC_HDR }, + { L"TIF", WIC_CODEC_TIFF }, + { L"TIFF", WIC_CODEC_TIFF }, + { L"WDP", WIC_CODEC_WMP }, + { L"HDP", CODEC_HDP }, + { L"JXR", CODEC_JXR }, +#ifdef USE_OPENEXR + { L"EXR", CODEC_EXR }, +#endif + { nullptr, CODEC_DDS } +}; + +const SValue g_pFeatureLevels[] = // valid feature levels for -fl for maximimum size +{ + { L"9.1", 2048 }, + { L"9.2", 2048 }, + { L"9.3", 4096 }, + { L"10.0", 8192 }, + { L"10.1", 8192 }, + { L"11.0", 16384 }, + { L"11.1", 16384 }, + { L"12.0", 16384 }, + { L"12.1", 16384 }, + { nullptr, 0 }, +}; + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#pragma warning( disable : 4616 6211 ) + +namespace +{ + inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } + + struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } }; + + typedef public std::unique_ptr ScopedFindHandle; + + inline static bool ispow2(size_t x) + { + return ((x != 0) && !(x & (x - 1))); + } + +#pragma prefast(disable : 26018, "Only used with static internal arrays") + + DWORD LookupByName(const wchar_t *pName, const SValue *pArray) + { + while (pArray->pName) + { + if (!_wcsicmp(pName, pArray->pName)) + return pArray->dwValue; + + pArray++; + } + + return 0; + } + + + const wchar_t* LookupByValue(DWORD pValue, const SValue *pArray) + { + while (pArray->pName) + { + if (pValue == pArray->dwValue) + return pArray->pName; + + pArray++; + } + + return L""; + } + + + void SearchForFiles(const wchar_t* path, std::list& files, bool recursive) + { + // Process files + WIN32_FIND_DATA findData = {}; + ScopedFindHandle hFile(safe_handle(FindFirstFileExW(path, + FindExInfoBasic, &findData, + FindExSearchNameMatch, nullptr, + FIND_FIRST_EX_LARGE_FETCH))); + if (hFile) + { + for (;;) + { + if (!(findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY))) + { + wchar_t drive[_MAX_DRIVE] = {}; + wchar_t dir[_MAX_DIR] = {}; + _wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0); + + SConversion conv; + _wmakepath_s(conv.szSrc, drive, dir, findData.cFileName, nullptr); + files.push_back(conv); + } + + if (!FindNextFile(hFile.get(), &findData)) + break; + } + } + + // Process directories + if (recursive) + { + wchar_t searchDir[MAX_PATH] = {}; + { + wchar_t drive[_MAX_DRIVE] = {}; + wchar_t dir[_MAX_DIR] = {}; + _wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0); + _wmakepath_s(searchDir, drive, dir, L"*", nullptr); + } + + hFile.reset(safe_handle(FindFirstFileExW(searchDir, + FindExInfoBasic, &findData, + FindExSearchLimitToDirectories, nullptr, + FIND_FIRST_EX_LARGE_FETCH))); + if (!hFile) + return; + + for (;;) + { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (findData.cFileName[0] != L'.') + { + wchar_t subdir[MAX_PATH] = {}; + + { + wchar_t drive[_MAX_DRIVE] = {}; + wchar_t dir[_MAX_DIR] = {}; + wchar_t fname[_MAX_FNAME] = {}; + wchar_t ext[_MAX_FNAME] = {}; + _wsplitpath_s(path, drive, dir, fname, ext); + wcscat_s(dir, findData.cFileName); + _wmakepath_s(subdir, drive, dir, fname, ext); + } + + SearchForFiles(subdir, files, recursive); + } + } + + if (!FindNextFile(hFile.get(), &findData)) + break; + } + } + } + + + void PrintFormat(DXGI_FORMAT Format) + { + for (const SValue *pFormat = g_pFormats; pFormat->pName; pFormat++) + { + if ((DXGI_FORMAT)pFormat->dwValue == Format) + { + wprintf(pFormat->pName); + return; + } + } + + for (const SValue *pFormat = g_pReadOnlyFormats; pFormat->pName; pFormat++) + { + if ((DXGI_FORMAT)pFormat->dwValue == Format) + { + wprintf(pFormat->pName); + return; + } + } + + wprintf(L"*UNKNOWN*"); + } + + + void PrintInfo(const TexMetadata& info, bool isXbox) + { + wprintf(L" (%Iux%Iu", info.width, info.height); + + if (TEX_DIMENSION_TEXTURE3D == info.dimension) + wprintf(L"x%Iu", info.depth); + + if (info.mipLevels > 1) + wprintf(L",%Iu", info.mipLevels); + + if (info.arraySize > 1) + wprintf(L",%Iu", info.arraySize); + + wprintf(L" "); + PrintFormat(info.format); + + switch (info.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + wprintf((info.arraySize > 1) ? L" 1DArray" : L" 1D"); + break; + + case TEX_DIMENSION_TEXTURE2D: + if (info.IsCubemap()) + { + wprintf((info.arraySize > 6) ? L" CubeArray" : L" Cube"); + } + else + { + wprintf((info.arraySize > 1) ? L" 2DArray" : L" 2D"); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + wprintf(L" 3D"); + break; + } + + switch (info.GetAlphaMode()) + { + case TEX_ALPHA_MODE_OPAQUE: + wprintf(L" \x0e0:Opaque"); + break; + case TEX_ALPHA_MODE_PREMULTIPLIED: + wprintf(L" \x0e0:PM"); + break; + case TEX_ALPHA_MODE_STRAIGHT: + wprintf(L" \x0e0:NonPM"); + break; + } + + if (isXbox) + { + wprintf(L" Xbox"); + } + + wprintf(L")"); + } + + + void PrintList(size_t cch, const SValue *pValue) + { + while (pValue->pName) + { + size_t cchName = wcslen(pValue->pName); + + if (cch + cchName + 2 >= 80) + { + wprintf(L"\n "); + cch = 6; + } + + wprintf(L"%ls ", pValue->pName); + cch += cchName + 2; + pValue++; + } + + wprintf(L"\n"); + } + + + void PrintLogo() + { + wprintf(L"Microsoft (R) DirectX Texture Converter for Xbox One\n"); + wprintf(L"Copyright (C) Microsoft Corp. All rights reserved.\n"); +#ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); +#endif + wprintf(L"\n"); + } + + + _Success_(return != false) + bool GetDXGIFactory(_Outptr_ IDXGIFactory1** pFactory) + { + if (!pFactory) + return false; + + *pFactory = nullptr; + + typedef HRESULT(WINAPI* pfn_CreateDXGIFactory1)(REFIID riid, _Out_ void **ppFactory); + + static pfn_CreateDXGIFactory1 s_CreateDXGIFactory1 = nullptr; + + if (!s_CreateDXGIFactory1) + { + HMODULE hModDXGI = LoadLibrary(L"dxgi.dll"); + if (!hModDXGI) + return false; + + s_CreateDXGIFactory1 = reinterpret_cast(reinterpret_cast(GetProcAddress(hModDXGI, "CreateDXGIFactory1"))); + if (!s_CreateDXGIFactory1) + return false; + } + + return SUCCEEDED(s_CreateDXGIFactory1(IID_PPV_ARGS(pFactory))); + } + + + void PrintUsage() + { + PrintLogo(); + + wprintf(L"Usage: texconv \n\n"); + wprintf(L" -r wildcard filename search is recursive\n"); + wprintf(L" -w width\n"); + wprintf(L" -h height\n"); + wprintf(L" -m miplevels\n"); + wprintf(L" -f format\n"); + wprintf(L" -if image filtering\n"); + wprintf(L" -srgb{i|o} sRGB {input, output}\n"); + wprintf(L" -px name prefix\n"); + wprintf(L" -sx name suffix\n"); + wprintf(L" -o output directory\n"); + wprintf(L" -y overwrite existing output file (if any)\n"); + wprintf(L" -ft output file type\n"); + wprintf(L" -hflip horizonal flip of source image\n"); + wprintf(L" -vflip vertical flip of source image\n"); + wprintf(L" -sepalpha resize/generate mips alpha channel separately\n"); + wprintf(L" from color channels\n"); + wprintf(L" -wrap, -mirror texture addressing mode (wrap, mirror, or clamp)\n"); + wprintf(L" -pmalpha convert final texture to use premultiplied alpha\n"); + wprintf(L" -alpha convert premultiplied alpha to straight alpha\n"); + wprintf(L" -pow2 resize to fit a power-of-2, respecting aspect ratio\n"); + wprintf( + L" -nmap converts height-map to normal-map\n" + L" options must be one or more of\n" + L" r, g, b, a, l, m, u, v, i, o\n"); + wprintf(L" -nmapamp normal map amplitude (defaults to 1.0)\n"); + wprintf(L" -fl Set maximum feature level target (defaults to 11.0)\n"); + wprintf(L"\n (DDS input only)\n"); + wprintf(L" -t{u|f} TYPELESS format is treated as UNORM or FLOAT\n"); + wprintf(L" -dword Use DWORD instead of BYTE alignment\n"); + wprintf(L" -badtails Fix for older DXTn with bad mipchain tails\n"); + wprintf(L" -xlum expand legacy L8, L16, and A8P8 formats\n"); + wprintf(L"\n (DDS output only)\n"); + wprintf(L" -dx10 Force use of 'DX10' extended header\n"); + wprintf(L" -xbox Tile and use 'XBOX' variant of DDS\n"); + wprintf(L" -xgmode Tile using provided memory layout mode\n"); + wprintf(L"\n -nologo suppress copyright message\n"); + wprintf(L" -timing Display elapsed processing time\n\n"); +#ifdef _OPENMP + wprintf(L" -singleproc Do not use multi-threaded compression\n"); +#endif + wprintf(L" -gpu Select GPU for DirectCompute-based codecs (0 is default)\n"); + wprintf(L" -nogpu Do not use DirectCompute-based codecs\n"); + wprintf(L" -bcuniform Use uniform rather than perceptual weighting for BC1-3\n"); + wprintf(L" -bcdither Use dithering for BC1-3\n"); + wprintf(L" -bcmax Use exhaustive compression (BC7 only)\n"); + wprintf(L" -bcquick Use quick compression (BC7 only)\n"); + wprintf(L" -wicq When writing images with WIC use quality (0.0 to 1.0)\n"); + wprintf(L" -wiclossless When writing images with WIC use lossless mode\n"); + wprintf(L" -wicmulti When writing images with WIC encode multiframe images\n"); + wprintf( + L" -aw BC7 GPU compressor weighting for alpha error metric\n" + L" (defaults to 1.0)\n"); + wprintf(L" -c colorkey (a.k.a. chromakey) transparency\n"); + wprintf(L" -tonemap Apply a tonemap operator based on maximum luminance\n"); + wprintf(L" -x2bias Enable *2 - 1 conversion cases for unorm/pos-only-float\n"); + wprintf(L" -flist use text file with a list of input files (one per line)\n"); + + wprintf(L"\n : "); + PrintList(13, g_pFormats); + + wprintf(L"\n : "); + PrintList(13, g_pFilters); + + wprintf(L"\n : "); + PrintList(15, g_pSaveFileTypes); + + wprintf(L"\n : "); + PrintList(13, g_pFeatureLevels); + + ComPtr dxgiFactory; + if (GetDXGIFactory(dxgiFactory.GetAddressOf())) + { + wprintf(L"\n :\n"); + + ComPtr adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters(adapterIndex, adapter.ReleaseAndGetAddressOf()); ++adapterIndex) + { + DXGI_ADAPTER_DESC desc; + if (SUCCEEDED(adapter->GetDesc(&desc))) + { + wprintf(L" %u: VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + } + } + } + } + + + _Success_(return != false) + bool CreateDevice(int adapter, _Outptr_ ID3D11Device** pDevice) + { + if (!pDevice) + return false; + + *pDevice = nullptr; + + static PFN_D3D11_CREATE_DEVICE s_DynamicD3D11CreateDevice = nullptr; + + if (!s_DynamicD3D11CreateDevice) + { + HMODULE hModD3D11 = LoadLibrary(L"d3d11.dll"); + if (!hModD3D11) + return false; + + s_DynamicD3D11CreateDevice = reinterpret_cast(reinterpret_cast(GetProcAddress(hModD3D11, "D3D11CreateDevice"))); + if (!s_DynamicD3D11CreateDevice) + return false; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + + UINT createDeviceFlags = 0; +#ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + ComPtr pAdapter; + if (adapter >= 0) + { + ComPtr dxgiFactory; + if (GetDXGIFactory(dxgiFactory.GetAddressOf())) + { + if (FAILED(dxgiFactory->EnumAdapters(adapter, pAdapter.GetAddressOf()))) + { + wprintf(L"\nERROR: Invalid GPU adapter index (%d)!\n", adapter); + return false; + } + } + } + + D3D_FEATURE_LEVEL fl; + HRESULT hr = s_DynamicD3D11CreateDevice(pAdapter.Get(), + (pAdapter) ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, + nullptr, createDeviceFlags, featureLevels, _countof(featureLevels), + D3D11_SDK_VERSION, pDevice, &fl, nullptr); + if (SUCCEEDED(hr)) + { + if (fl < D3D_FEATURE_LEVEL_11_0) + { + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts; + hr = (*pDevice)->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts)); + if (FAILED(hr)) + memset(&hwopts, 0, sizeof(hwopts)); + + if (!hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x) + { + if (*pDevice) + { + (*pDevice)->Release(); + *pDevice = nullptr; + } + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + } + + if (SUCCEEDED(hr)) + { + ComPtr dxgiDevice; + hr = (*pDevice)->QueryInterface(IID_PPV_ARGS(dxgiDevice.GetAddressOf())); + if (SUCCEEDED(hr)) + { + hr = dxgiDevice->GetAdapter(pAdapter.ReleaseAndGetAddressOf()); + if (SUCCEEDED(hr)) + { + DXGI_ADAPTER_DESC desc; + hr = pAdapter->GetDesc(&desc); + if (SUCCEEDED(hr)) + { + wprintf(L"\n[Using DirectCompute on \"%ls\"]\n", desc.Description); + } + } + } + + return true; + } + else + return false; + } + + + void FitPowerOf2(size_t origx, size_t origy, size_t& targetx, size_t& targety, size_t maxsize) + { + float origAR = float(origx) / float(origy); + + if (origx > origy) + { + size_t x; + for (x = maxsize; x > 1; x >>= 1) { if (x <= targetx) break; }; + targetx = x; + + float bestScore = FLT_MAX; + for (size_t y = maxsize; y > 0; y >>= 1) + { + float score = fabs((float(x) / float(y)) - origAR); + if (score < bestScore) + { + bestScore = score; + targety = y; + } + } + } + else + { + size_t y; + for (y = maxsize; y > 1; y >>= 1) { if (y <= targety) break; }; + targety = y; + + float bestScore = FLT_MAX; + for (size_t x = maxsize; x > 0; x >>= 1) + { + float score = fabs((float(x) / float(y)) - origAR); + if (score < bestScore) + { + bestScore = score; + targetx = x; + } + } + } + } +} + + +//-------------------------------------------------------------------------------------- +// Entry-point +//-------------------------------------------------------------------------------------- +#pragma prefast(disable : 28198, "Command-line tool, frees all memory on exit") + +int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) +{ + // Parameters and defaults + size_t width = 0; + size_t height = 0; + size_t mipLevels = 0; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + DWORD dwFilter = TEX_FILTER_DEFAULT; + DWORD dwSRGB = 0; + DWORD dwConvert = 0; + DWORD dwCompress = TEX_COMPRESS_DEFAULT; + DWORD dwFilterOpts = 0; + DWORD FileType = CODEC_DDS; + DWORD maxSize = 16384; + int adapter = -1; + float alphaWeight = 1.f; + DWORD dwNormalMap = 0; + float nmapAmplitude = 1.f; + float wicQuality = -1.f; + DWORD colorKey = 0; + + wchar_t szPrefix[MAX_PATH]; + wchar_t szSuffix[MAX_PATH]; + wchar_t szOutputDir[MAX_PATH]; + + szPrefix[0] = 0; + szSuffix[0] = 0; + szOutputDir[0] = 0; + + // Initialize COM (needed for WIC) + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + if (FAILED(hr)) + { + wprintf(L"Failed to initialize COM (%08X)\n", hr); + return 1; + } + + // Process command line + DWORD64 dwOptions = 0; + std::list conversion; + + for (int iArg = 1; iArg < argc; iArg++) + { + PWSTR pArg = argv[iArg]; + + if (('-' == pArg[0]) || ('/' == pArg[0])) + { + pArg++; + PWSTR pValue; + + for (pValue = pArg; *pValue && (':' != *pValue); pValue++); + + if (*pValue) + *pValue++ = 0; + + DWORD dwOption = LookupByName(pArg, g_pOptions); + + if (!dwOption || (dwOptions & (DWORD64(1) << dwOption))) + { + PrintUsage(); + return 1; + } + + dwOptions |= (DWORD64(1) << dwOption); + + // Handle options with additional value parameter + switch (dwOption) + { + case OPT_WIDTH: + case OPT_HEIGHT: + case OPT_MIPLEVELS: + case OPT_FORMAT: + case OPT_FILTER: + case OPT_PREFIX: + case OPT_SUFFIX: + case OPT_OUTPUTDIR: + case OPT_FILETYPE: + case OPT_GPU: + case OPT_FEATURE_LEVEL: + case OPT_ALPHA_WEIGHT: + case OPT_NORMAL_MAP: + case OPT_NORMAL_MAP_AMPLITUDE: + case OPT_WIC_QUALITY: + case OPT_COLORKEY: + case OPT_FILELIST: + case OPT_XGMODE: + if (!*pValue) + { + if ((iArg + 1 >= argc)) + { + PrintUsage(); + return 1; + } + + iArg++; + pValue = argv[iArg]; + } + break; + } + + switch (dwOption) + { + case OPT_WIDTH: + if (swscanf_s(pValue, L"%Iu", &width) != 1) + { + wprintf(L"Invalid value specified with -w (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_HEIGHT: + if (swscanf_s(pValue, L"%Iu", &height) != 1) + { + wprintf(L"Invalid value specified with -h (%ls)\n", pValue); + printf("\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_MIPLEVELS: + if (swscanf_s(pValue, L"%Iu", &mipLevels) != 1) + { + wprintf(L"Invalid value specified with -m (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_FORMAT: + format = (DXGI_FORMAT)LookupByName(pValue, g_pFormats); + if (!format) + { + wprintf(L"Invalid value specified with -f (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_FILTER: + dwFilter = LookupByName(pValue, g_pFilters); + if (!dwFilter) + { + wprintf(L"Invalid value specified with -if (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_SRGBI: + dwSRGB |= TEX_FILTER_SRGB_IN; + break; + + case OPT_SRGBO: + dwSRGB |= TEX_FILTER_SRGB_OUT; + break; + + case OPT_SRGB: + dwSRGB |= TEX_FILTER_SRGB; + break; + + case OPT_SEPALPHA: + dwFilterOpts |= TEX_FILTER_SEPARATE_ALPHA; + break; + + case OPT_PREFIX: + wcscpy_s(szPrefix, MAX_PATH, pValue); + break; + + case OPT_SUFFIX: + wcscpy_s(szSuffix, MAX_PATH, pValue); + break; + + case OPT_OUTPUTDIR: + wcscpy_s(szOutputDir, MAX_PATH, pValue); + break; + + case OPT_FILETYPE: + FileType = LookupByName(pValue, g_pSaveFileTypes); + if (!FileType) + { + wprintf(L"Invalid value specified with -ft (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_PREMUL_ALPHA: + if (dwOptions & (DWORD64(1) << OPT_DEMUL_ALPHA)) + { + wprintf(L"Can't use -pmalpha and -alpha at same time\n\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_DEMUL_ALPHA: + if (dwOptions & (DWORD64(1) << OPT_PREMUL_ALPHA)) + { + wprintf(L"Can't use -pmalpha and -alpha at same time\n\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_TA_WRAP: + if (dwFilterOpts & TEX_FILTER_MIRROR) + { + wprintf(L"Can't use -wrap and -mirror at same time\n\n"); + PrintUsage(); + return 1; + } + dwFilterOpts |= TEX_FILTER_WRAP; + break; + + case OPT_TA_MIRROR: + if (dwFilterOpts & TEX_FILTER_WRAP) + { + wprintf(L"Can't use -wrap and -mirror at same time\n\n"); + PrintUsage(); + return 1; + } + dwFilterOpts |= TEX_FILTER_MIRROR; + break; + + case OPT_NORMAL_MAP: + { + dwNormalMap = 0; + + if (wcschr(pValue, L'l')) + { + dwNormalMap |= CNMAP_CHANNEL_LUMINANCE; + } + else if (wcschr(pValue, L'r')) + { + dwNormalMap |= CNMAP_CHANNEL_RED; + } + else if (wcschr(pValue, L'g')) + { + dwNormalMap |= CNMAP_CHANNEL_GREEN; + } + else if (wcschr(pValue, L'b')) + { + dwNormalMap |= CNMAP_CHANNEL_BLUE; + } + else if (wcschr(pValue, L'a')) + { + dwNormalMap |= CNMAP_CHANNEL_ALPHA; + } + else + { + wprintf(L"Invalid value specified for -nmap (%ls), missing l, r, g, b, or a\n\n", pValue); + PrintUsage(); + return 1; + } + + if (wcschr(pValue, L'm')) + { + dwNormalMap |= CNMAP_MIRROR; + } + else + { + if (wcschr(pValue, L'u')) + { + dwNormalMap |= CNMAP_MIRROR_U; + } + if (wcschr(pValue, L'v')) + { + dwNormalMap |= CNMAP_MIRROR_V; + } + } + + if (wcschr(pValue, L'i')) + { + dwNormalMap |= CNMAP_INVERT_SIGN; + } + + if (wcschr(pValue, L'o')) + { + dwNormalMap |= CNMAP_COMPUTE_OCCLUSION; + } + } + break; + + case OPT_NORMAL_MAP_AMPLITUDE: + if (!dwNormalMap) + { + wprintf(L"-nmapamp requires -nmap\n\n"); + PrintUsage(); + return 1; + } + else if (swscanf_s(pValue, L"%f", &nmapAmplitude) != 1) + { + wprintf(L"Invalid value specified with -nmapamp (%ls)\n\n", pValue); + PrintUsage(); + return 1; + } + else if (nmapAmplitude < 0.f) + { + wprintf(L"Normal map amplitude must be positive (%ls)\n\n", pValue); + PrintUsage(); + return 1; + } + break; + + case OPT_GPU: + if (swscanf_s(pValue, L"%d", &adapter) != 1) + { + wprintf(L"Invalid value specified with -gpu (%ls)\n\n", pValue); + PrintUsage(); + return 1; + } + else if (adapter < 0) + { + wprintf(L"Adapter index (%ls)\n\n", pValue); + PrintUsage(); + return 1; + } + break; + + case OPT_FEATURE_LEVEL: + maxSize = LookupByName(pValue, g_pFeatureLevels); + if (!maxSize) + { + wprintf(L"Invalid value specified with -fl (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_ALPHA_WEIGHT: + if (swscanf_s(pValue, L"%f", &alphaWeight) != 1) + { + wprintf(L"Invalid value specified with -aw (%ls)\n", pValue); + wprintf(L"\n"); + PrintUsage(); + return 1; + } + else if (alphaWeight < 0.f) + { + wprintf(L"-aw (%ls) parameter must be positive\n", pValue); + wprintf(L"\n"); + return 1; + } + break; + + case OPT_COMPRESS_UNIFORM: + dwCompress |= TEX_COMPRESS_UNIFORM; + break; + + case OPT_COMPRESS_MAX: + if (dwCompress & TEX_COMPRESS_BC7_QUICK) + { + wprintf(L"Can't use -bcmax and -bcquick at same time\n\n"); + PrintUsage(); + return 1; + } + dwCompress |= TEX_COMPRESS_BC7_USE_3SUBSETS; + break; + + case OPT_COMPRESS_QUICK: + if (dwCompress & TEX_COMPRESS_BC7_USE_3SUBSETS) + { + wprintf(L"Can't use -bcmax and -bcquick at same time\n\n"); + PrintUsage(); + return 1; + } + dwCompress |= TEX_COMPRESS_BC7_QUICK; + break; + + case OPT_COMPRESS_DITHER: + dwCompress |= TEX_COMPRESS_DITHER; + break; + + case OPT_WIC_QUALITY: + if (swscanf_s(pValue, L"%f", &wicQuality) != 1 + || (wicQuality < 0.f) + || (wicQuality > 1.f)) + { + wprintf(L"Invalid value specified with -wicq (%ls)\n", pValue); + printf("\n"); + PrintUsage(); + return 1; + } + break; + + case OPT_COLORKEY: + if (swscanf_s(pValue, L"%x", &colorKey) != 1) + { + printf("Invalid value specified with -c (%ls)\n", pValue); + printf("\n"); + PrintUsage(); + return 1; + } + colorKey &= 0xFFFFFF; + break; + + case OPT_X2_BIAS: + dwConvert |= TEX_FILTER_FLOAT_X2BIAS; + break; + + case OPT_FILELIST: + { + std::wifstream inFile(pValue); + if (!inFile) + { + wprintf(L"Error opening -flist file %ls\n", pValue); + return 1; + } + wchar_t fname[1024] = {}; + for (;;) + { + inFile >> fname; + if (!inFile) + break; + + if (*fname == L'#') + { + // Comment + } + else if (*fname == L'-') + { + wprintf(L"Command-line arguments not supported in -flist file\n"); + return 1; + } + else if (wcspbrk(fname, L"?*") != nullptr) + { + wprintf(L"Wildcards not supported in -flist file\n"); + return 1; + } + else + { + SConversion conv; + wcscpy_s(conv.szSrc, MAX_PATH, fname); + conversion.push_back(conv); + } + + inFile.ignore(1000, '\n'); + } + inFile.close(); + } + break; + + case OPT_XGMODE: +#if _XDK_VER >= 0x3F6803F3 /* XDK Edition 170600 */ + { + static const SValue s_pXGModes[] = + { + { L"xboxone", XG_HARDWARE_VERSION_XBOX_ONE }, + { L"xboxonex", XG_HARDWARE_VERSION_XBOX_ONE_X }, + { nullptr, 0 }, + }; + + DWORD mode = LookupByName(pValue, s_pXGModes); + if (!mode) + { + printf("Invalid value specified with -xgmode (%ls)\n", pValue); + wprintf(L"\n : "); + PrintList(14, s_pXGModes); + return 1; + }; + + XGSetHardwareVersion(static_cast(mode)); + break; + } +#else + printf("WARNING: -xgmode switch ignored\n"); +#endif + } + } + else if (wcspbrk(pArg, L"?*") != nullptr) + { + size_t count = conversion.size(); + SearchForFiles(pArg, conversion, (dwOptions & (DWORD64(1) << OPT_RECURSIVE)) != 0); + if (conversion.size() <= count) + { + wprintf(L"No matching files found for %ls\n", pArg); + return 1; + } + } + else + { + SConversion conv; + wcscpy_s(conv.szSrc, MAX_PATH, pArg); + + conv.szDest[0] = 0; + + conversion.push_back(conv); + } + } + + if (conversion.empty()) + { + PrintUsage(); + return 0; + } + + if (~dwOptions & (DWORD64(1) << OPT_NOLOGO)) + PrintLogo(); + + // Work out out filename prefix and suffix + if (szOutputDir[0] && (L'\\' != szOutputDir[wcslen(szOutputDir) - 1])) + wcscat_s(szOutputDir, MAX_PATH, L"\\"); + + if (szPrefix[0]) + wcscat_s(szOutputDir, MAX_PATH, szPrefix); + + wcscpy_s(szPrefix, MAX_PATH, szOutputDir); + + const wchar_t* fileTypeName = LookupByValue(FileType, g_pSaveFileTypes); + + if (fileTypeName) + { + wcscat_s(szSuffix, MAX_PATH, L"."); + wcscat_s(szSuffix, MAX_PATH, fileTypeName); + } + else + { + wcscat_s(szSuffix, MAX_PATH, L".unknown"); + } + + if (FileType != CODEC_DDS) + { + mipLevels = 1; + } + + LARGE_INTEGER qpcFreq; + if (!QueryPerformanceFrequency(&qpcFreq)) + { + qpcFreq.QuadPart = 0; + } + + + LARGE_INTEGER qpcStart; + if (!QueryPerformanceCounter(&qpcStart)) + { + qpcStart.QuadPart = 0; + } + + // Convert images + bool nonpow2warn = false; + bool non4bc = false; + ComPtr pDevice; + + for (auto pConv = conversion.begin(); pConv != conversion.end(); ++pConv) + { + if (pConv != conversion.begin()) + wprintf(L"\n"); + + // Load source image + wprintf(L"reading %ls", pConv->szSrc); + fflush(stdout); + + wchar_t ext[_MAX_EXT]; + wchar_t fname[_MAX_FNAME]; + _wsplitpath_s(pConv->szSrc, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT); + + TexMetadata info; + std::unique_ptr image(new (std::nothrow) ScratchImage); + + if (!image) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + bool isXbox = false; + if (_wcsicmp(ext, L".dds") == 0) + { + hr = Xbox::GetMetadataFromDDSFile(pConv->szSrc, info, isXbox); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + + if (isXbox) + { + Xbox::XboxImage xbox; + + hr = Xbox::LoadFromDDSFile(pConv->szSrc, &info, xbox); + if (SUCCEEDED(hr)) + { + hr = Xbox::Detile(xbox, *image); + } + } + else + { + DWORD ddsFlags = DDS_FLAGS_NONE; + if (dwOptions & (DWORD64(1) << OPT_DDS_DWORD_ALIGN)) + ddsFlags |= DDS_FLAGS_LEGACY_DWORD; + if (dwOptions & (DWORD64(1) << OPT_EXPAND_LUMINANCE)) + ddsFlags |= DDS_FLAGS_EXPAND_LUMINANCE; + if (dwOptions & (DWORD64(1) << OPT_DDS_BAD_DXTN_TAILS)) + ddsFlags |= DDS_FLAGS_BAD_DXTN_TAILS; + + hr = LoadFromDDSFile(pConv->szSrc, ddsFlags, &info, *image); + } + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + + if (IsTypeless(info.format)) + { + if (dwOptions & (DWORD64(1) << OPT_TYPELESS_UNORM)) + { + info.format = MakeTypelessUNORM(info.format); + } + else if (dwOptions & (DWORD64(1) << OPT_TYPELESS_FLOAT)) + { + info.format = MakeTypelessFLOAT(info.format); + } + + if (IsTypeless(info.format)) + { + wprintf(L" FAILED due to Typeless format %d\n", info.format); + continue; + } + + image->OverrideFormat(info.format); + } + } + else if (_wcsicmp(ext, L".tga") == 0) + { + hr = LoadFromTGAFile(pConv->szSrc, &info, *image); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + } + else if (_wcsicmp(ext, L".hdr") == 0) + { + hr = LoadFromHDRFile(pConv->szSrc, &info, *image); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + } +#ifdef USE_OPENEXR + else if (_wcsicmp(ext, L".exr") == 0) + { + hr = LoadFromEXRFile(pConv->szSrc, &info, *image); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + } +#endif + else + { + // WIC shares the same filter values for mode and dither + static_assert(WIC_FLAGS_DITHER == TEX_FILTER_DITHER, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_DITHER_DIFFUSION == TEX_FILTER_DITHER_DIFFUSION, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_POINT == TEX_FILTER_POINT, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_LINEAR == TEX_FILTER_LINEAR, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_CUBIC == TEX_FILTER_CUBIC, "WIC_FLAGS_* & TEX_FILTER_* should match"); + static_assert(WIC_FLAGS_FILTER_FANT == TEX_FILTER_FANT, "WIC_FLAGS_* & TEX_FILTER_* should match"); + + DWORD wicFlags = dwFilter; + if (FileType == CODEC_DDS) + wicFlags |= WIC_FLAGS_ALL_FRAMES; + + hr = LoadFromWICFile(pConv->szSrc, wicFlags, &info, *image); + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + } + + PrintInfo(info, isXbox); + + size_t tMips = (!mipLevels && info.mipLevels > 1) ? info.mipLevels : mipLevels; + + bool sizewarn = false; + + size_t twidth = (!width) ? info.width : width; + if (twidth > maxSize) + { + if (!width) + twidth = maxSize; + else + sizewarn = true; + } + + size_t theight = (!height) ? info.height : height; + if (theight > maxSize) + { + if (!height) + theight = maxSize; + else + sizewarn = true; + } + + if (sizewarn) + { + wprintf(L"\nWARNING: Target size exceeds maximum size for feature level (%u)\n", maxSize); + } + + if (dwOptions & (DWORD64(1) << OPT_FIT_POWEROF2)) + { + FitPowerOf2(info.width, info.height, twidth, theight, maxSize); + } + + // Convert texture + wprintf(L" as"); + fflush(stdout); + + // --- Planar ------------------------------------------------------------------ + if (IsPlanar(info.format)) + { + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = ConvertToSinglePlane(img, nimg, info, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [converttosingleplane] (%x)\n", hr); + continue; + } + + auto& tinfo = timage->GetMetadata(); + + info.format = tinfo.format; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + } + + DXGI_FORMAT tformat = (format == DXGI_FORMAT_UNKNOWN) ? info.format : format; + + // --- Decompress -------------------------------------------------------------- + std::unique_ptr cimage; + if (IsCompressed(info.format)) + { + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = Decompress(img, nimg, info, DXGI_FORMAT_UNKNOWN /* picks good default */, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [decompress] (%x)\n", hr); + continue; + } + + auto& tinfo = timage->GetMetadata(); + + info.format = tinfo.format; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + if (FileType == CODEC_DDS) + { + // Keep the original compressed image in case we can reuse it + cimage.reset(image.release()); + image.reset(timage.release()); + } + else + { + image.swap(timage); + } + } + + // --- Undo Premultiplied Alpha (if requested) --------------------------------- + if ((dwOptions & (DWORD64(1) << OPT_DEMUL_ALPHA)) + && HasAlpha(info.format) + && info.format != DXGI_FORMAT_A8_UNORM) + { + if (info.GetAlphaMode() == TEX_ALPHA_MODE_STRAIGHT) + { + printf("\nWARNING: Image is already using straight alpha\n"); + } + else if (!info.IsPMAlpha()) + { + printf("\nWARNING: Image is not using premultipled alpha\n"); + } + else + { + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = PremultiplyAlpha(img, nimg, info, TEX_PMALPHA_REVERSE | dwSRGB, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [demultiply alpha] (%x)\n", hr); + continue; + } + + auto& tinfo = timage->GetMetadata(); + info.miscFlags2 = tinfo.miscFlags2; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + } + + // --- Flip/Rotate ------------------------------------------------------------- + if (dwOptions & ((DWORD64(1) << OPT_HFLIP) | (DWORD64(1) << OPT_VFLIP))) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + DWORD dwFlags = 0; + + if (dwOptions & (DWORD64(1) << OPT_HFLIP)) + dwFlags |= TEX_FR_FLIP_HORIZONTAL; + + if (dwOptions & (DWORD64(1) << OPT_VFLIP)) + dwFlags |= TEX_FR_FLIP_VERTICAL; + + assert(dwFlags != 0); + + hr = FlipRotate(image->GetImages(), image->GetImageCount(), image->GetMetadata(), dwFlags, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [fliprotate] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + + assert(tinfo.width == twidth && tinfo.height == theight); + + info.width = tinfo.width; + info.height = tinfo.height; + + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + + // --- Resize ------------------------------------------------------------------ + if (info.width != twidth || info.height != theight) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = Resize(image->GetImages(), image->GetImageCount(), image->GetMetadata(), twidth, theight, dwFilter | dwFilterOpts, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [resize] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + + assert(tinfo.width == twidth && tinfo.height == theight && tinfo.mipLevels == 1); + info.width = tinfo.width; + info.height = tinfo.height; + info.mipLevels = 1; + + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + + // --- Tonemap (if requested) -------------------------------------------------- + if (dwOptions & DWORD64(1) << OPT_TONEMAP) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + // Compute max luminosity across all images + XMVECTOR maxLum = XMVectorZero(); + hr = EvaluateImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(), + [&](const XMVECTOR* pixels, size_t width, size_t y) + { + UNREFERENCED_PARAMETER(y); + + for (size_t j = 0; j < width; ++j) + { + static const XMVECTORF32 s_luminance = { 0.3f, 0.59f, 0.11f, 0.f }; + + XMVECTOR v = *pixels++; + + v = XMVector3Dot(v, s_luminance); + + maxLum = XMVectorMax(v, maxLum); + } + }); + if (FAILED(hr)) + { + wprintf(L" FAILED [tonemap maxlum] (%x)\n", hr); + return 1; + } + + // Reinhard et al, "Photographic Tone Reproduction for Digital Images" + // http://www.cs.utah.edu/~reinhard/cdrom/ + maxLum = XMVectorMultiply(maxLum, maxLum); + + hr = TransformImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(), + [&](XMVECTOR* outPixels, const XMVECTOR* inPixels, size_t width, size_t y) + { + UNREFERENCED_PARAMETER(y); + + for (size_t j = 0; j < width; ++j) + { + XMVECTOR value = inPixels[j]; + + XMVECTOR scale = XMVectorDivide( + XMVectorAdd(g_XMOne, XMVectorDivide(value, maxLum)), + XMVectorAdd(g_XMOne, value)); + XMVECTOR nvalue = XMVectorMultiply(value, scale); + + value = XMVectorSelect(value, nvalue, g_XMSelect1110); + + outPixels[j] = value; + } + }, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [tonemap apply] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + tinfo; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + + // --- Convert ----------------------------------------------------------------- + if (dwOptions & (DWORD64(1) << OPT_NORMAL_MAP)) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + DXGI_FORMAT nmfmt = tformat; + if (IsCompressed(tformat)) + { + nmfmt = (dwNormalMap & CNMAP_COMPUTE_OCCLUSION) ? DXGI_FORMAT_R32G32B32A32_FLOAT : DXGI_FORMAT_R32G32B32_FLOAT; + } + + hr = ComputeNormalMap(image->GetImages(), image->GetImageCount(), image->GetMetadata(), dwNormalMap, nmapAmplitude, nmfmt, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [normalmap] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + + assert(tinfo.format == nmfmt); + info.format = tinfo.format; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + else if (info.format != tformat && !IsCompressed(tformat)) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = Convert(image->GetImages(), image->GetImageCount(), image->GetMetadata(), tformat, + dwFilter | dwFilterOpts | dwSRGB | dwConvert, TEX_THRESHOLD_DEFAULT, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [convert] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + + assert(tinfo.format == tformat); + info.format = tinfo.format; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + + // --- ColorKey/ChromaKey ------------------------------------------------------ + if ((dwOptions & (DWORD64(1) << OPT_COLORKEY)) + && HasAlpha(info.format)) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + XMVECTOR colorKeyValue = XMLoadColor(reinterpret_cast(&colorKey)); + + hr = TransformImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(), + [&](XMVECTOR* outPixels, const XMVECTOR* inPixels, size_t width, size_t y) + { + static const XMVECTORF32 s_tolerance = { 0.2f, 0.2f, 0.2f, 0.f }; + + UNREFERENCED_PARAMETER(y); + + for (size_t j = 0; j < width; ++j) + { + XMVECTOR value = inPixels[j]; + + if (XMVector3NearEqual(value, colorKeyValue, s_tolerance)) + { + value = g_XMZero; + } + else + { + value = XMVectorSelect(g_XMOne, value, g_XMSelect1110); + } + + outPixels[j] = value; + } + }, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [colorkey] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + tinfo; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + + // --- Generate mips ----------------------------------------------------------- + if (!ispow2(info.width) || !ispow2(info.height) || !ispow2(info.depth)) + { + if (info.dimension == TEX_DIMENSION_TEXTURE3D) + { + if (!tMips) + { + tMips = 1; + } + else + { + wprintf(L"\nERROR: Cannot generate mips for non-power-of-2 volume textures\n"); + return 1; + } + } + else if (!tMips || info.mipLevels != 1) + { + nonpow2warn = true; + } + } + + if ((!tMips || info.mipLevels != tMips) && (info.mipLevels != 1)) + { + // Mips generation only works on a single base image, so strip off existing mip levels + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + TexMetadata mdata = info; + mdata.mipLevels = 1; + hr = timage->Initialize(mdata); + if (FAILED(hr)) + { + wprintf(L" FAILED [copy to single level] (%x)\n", hr); + return 1; + } + + if (info.dimension == TEX_DIMENSION_TEXTURE3D) + { + for (size_t d = 0; d < info.depth; ++d) + { + hr = CopyRectangle(*image->GetImage(0, 0, d), Rect(0, 0, info.width, info.height), + *timage->GetImage(0, 0, d), TEX_FILTER_DEFAULT, 0, 0); + if (FAILED(hr)) + { + wprintf(L" FAILED [copy to single level] (%x)\n", hr); + return 1; + } + } + } + else + { + for (size_t i = 0; i < info.arraySize; ++i) + { + hr = CopyRectangle(*image->GetImage(0, i, 0), Rect(0, 0, info.width, info.height), + *timage->GetImage(0, i, 0), TEX_FILTER_DEFAULT, 0, 0); + if (FAILED(hr)) + { + wprintf(L" FAILED [copy to single level] (%x)\n", hr); + return 1; + } + } + } + + image.swap(timage); + info.mipLevels = image->GetMetadata().mipLevels; + + if (cimage && (tMips == 1)) + { + // Special case for trimming mips off compressed images and keeping the original compressed highest level mip + mdata = cimage->GetMetadata(); + mdata.mipLevels = 1; + hr = timage->Initialize(mdata); + if (FAILED(hr)) + { + wprintf(L" FAILED [copy compressed to single level] (%x)\n", hr); + return 1; + } + + if (mdata.dimension == TEX_DIMENSION_TEXTURE3D) + { + for (size_t d = 0; d < mdata.depth; ++d) + { + auto simg = cimage->GetImage(0, 0, d); + auto dimg = timage->GetImage(0, 0, d); + + memcpy_s(dimg->pixels, dimg->slicePitch, simg->pixels, simg->slicePitch); + } + } + else + { + for (size_t i = 0; i < mdata.arraySize; ++i) + { + auto simg = cimage->GetImage(0, i, 0); + auto dimg = timage->GetImage(0, i, 0); + + memcpy_s(dimg->pixels, dimg->slicePitch, simg->pixels, simg->slicePitch); + } + } + + cimage.swap(timage); + } + else + { + cimage.reset(); + } + } + + if ((!tMips || info.mipLevels != tMips) && (info.width > 1 || info.height > 1 || info.depth > 1)) + { + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + if (info.dimension == TEX_DIMENSION_TEXTURE3D) + { + hr = GenerateMipMaps3D(image->GetImages(), image->GetImageCount(), image->GetMetadata(), dwFilter | dwFilterOpts, tMips, *timage); + } + else + { + hr = GenerateMipMaps(image->GetImages(), image->GetImageCount(), image->GetMetadata(), dwFilter | dwFilterOpts, tMips, *timage); + } + if (FAILED(hr)) + { + wprintf(L" FAILED [mipmaps] (%x)\n", hr); + return 1; + } + + auto& tinfo = timage->GetMetadata(); + info.mipLevels = tinfo.mipLevels; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + + // --- Premultiplied alpha (if requested) -------------------------------------- + if ((dwOptions & (DWORD64(1) << OPT_PREMUL_ALPHA)) + && HasAlpha(info.format) + && info.format != DXGI_FORMAT_A8_UNORM) + { + if (info.IsPMAlpha()) + { + printf("\nWARNING: Image is already using premultiplied alpha\n"); + } + else + { + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + hr = PremultiplyAlpha(img, nimg, info, dwSRGB, *timage); + if (FAILED(hr)) + { + wprintf(L" FAILED [premultiply alpha] (%x)\n", hr); + continue; + } + + auto& tinfo = timage->GetMetadata(); + info.miscFlags2 = tinfo.miscFlags2; + + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + } + + // --- Compress ---------------------------------------------------------------- + if (IsCompressed(tformat) && (FileType == CODEC_DDS)) + { + if (cimage && (cimage->GetMetadata().format == tformat)) + { + // We never changed the image and it was already compressed in our desired format, use original data + image.reset(cimage.release()); + + auto& tinfo = image->GetMetadata(); + + if ((tinfo.width % 4) != 0 || (tinfo.height % 4) != 0) + { + non4bc = true; + } + + info.format = tinfo.format; + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + } + else + { + cimage.reset(); + + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + std::unique_ptr timage(new (std::nothrow) ScratchImage); + if (!timage) + { + wprintf(L"\nERROR: Memory allocation failed\n"); + return 1; + } + + bool bc6hbc7 = false; + switch (tformat) + { + 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: + bc6hbc7 = true; + + { + static bool s_tryonce = false; + + if (!s_tryonce) + { + s_tryonce = true; + + if (!(dwOptions & (DWORD64(1) << OPT_NOGPU))) + { + if (!CreateDevice(adapter, pDevice.GetAddressOf())) + wprintf(L"\nWARNING: DirectCompute is not available, using BC6H / BC7 CPU codec\n"); + } + else + { + wprintf(L"\nWARNING: using BC6H / BC7 CPU codec\n"); + } + } + } + break; + } + + DWORD cflags = dwCompress; +#ifdef _OPENMP + if (!(dwOptions & (DWORD64(1) << OPT_FORCE_SINGLEPROC))) + { + cflags |= TEX_COMPRESS_PARALLEL; + } +#endif + + if ((img->width % 4) != 0 || (img->height % 4) != 0) + { + non4bc = true; + } + + if (bc6hbc7 && pDevice) + { + hr = Compress(pDevice.Get(), img, nimg, info, tformat, dwCompress | dwSRGB, alphaWeight, *timage); + } + else + { + hr = Compress(img, nimg, info, tformat, cflags | dwSRGB, TEX_THRESHOLD_DEFAULT, *timage); + } + if (FAILED(hr)) + { + wprintf(L" FAILED [compress] (%x)\n", hr); + continue; + } + + auto& tinfo = timage->GetMetadata(); + + info.format = tinfo.format; + assert(info.width == tinfo.width); + assert(info.height == tinfo.height); + assert(info.depth == tinfo.depth); + assert(info.arraySize == tinfo.arraySize); + assert(info.mipLevels == tinfo.mipLevels); + assert(info.miscFlags == tinfo.miscFlags); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + } + } + else + { + cimage.reset(); + } + + // --- Set alpha mode ---------------------------------------------------------- + if (HasAlpha(info.format) + && info.format != DXGI_FORMAT_A8_UNORM) + { + if (image->IsAlphaAllOpaque()) + { + info.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE); + } + else if (info.IsPMAlpha()) + { + // Aleady set TEX_ALPHA_MODE_PREMULTIPLIED + } + else if (dwOptions & (DWORD64(1) << OPT_SEPALPHA)) + { + info.SetAlphaMode(TEX_ALPHA_MODE_CUSTOM); + } + else if (info.GetAlphaMode() == TEX_ALPHA_MODE_UNKNOWN) + { + info.SetAlphaMode(TEX_ALPHA_MODE_STRAIGHT); + } + } + else + { + info.SetAlphaMode(TEX_ALPHA_MODE_UNKNOWN); + } + + // --- Save result ------------------------------------------------------------- + { + auto img = image->GetImage(0, 0, 0); + assert(img); + size_t nimg = image->GetImageCount(); + + PrintInfo(info, (FileType == CODEC_DDS) && (dwOptions & (DWORD64(1) << OPT_USE_XBOX))); + wprintf(L"\n"); + + // Figure out dest filename + wchar_t *pchSlash, *pchDot; + + wcscpy_s(pConv->szDest, MAX_PATH, szPrefix); + + pchSlash = wcsrchr(pConv->szSrc, L'\\'); + if (pchSlash != 0) + wcscat_s(pConv->szDest, MAX_PATH, pchSlash + 1); + else + wcscat_s(pConv->szDest, MAX_PATH, pConv->szSrc); + + pchSlash = wcsrchr(pConv->szDest, '\\'); + pchDot = wcsrchr(pConv->szDest, '.'); + + if (pchDot > pchSlash) + *pchDot = 0; + + wcscat_s(pConv->szDest, MAX_PATH, szSuffix); + + // Write texture + wprintf(L"writing %ls", pConv->szDest); + fflush(stdout); + + if (~dwOptions & (DWORD64(1) << OPT_OVERWRITE)) + { + if (GetFileAttributesW(pConv->szDest) != INVALID_FILE_ATTRIBUTES) + { + wprintf(L"\nERROR: Output file already exists, use -y to overwrite:\n"); + continue; + } + } + + switch (FileType) + { + case CODEC_DDS: + if (dwOptions & (DWORD64(1) << OPT_USE_XBOX)) + { + Xbox::XboxImage xbox; + + hr = Xbox::Tile(img, nimg, info, xbox); + if (SUCCEEDED(hr)) + { + hr = Xbox::SaveToDDSFile(xbox, pConv->szDest); + } + } + else + { + hr = SaveToDDSFile(img, nimg, info, + (dwOptions & (DWORD64(1) << OPT_USE_DX10)) ? (DDS_FLAGS_FORCE_DX10_EXT | DDS_FLAGS_FORCE_DX10_EXT_MISC2) : DDS_FLAGS_NONE, + pConv->szDest); + } + break; + + case CODEC_TGA: + hr = SaveToTGAFile(img[0], pConv->szDest); + break; + + case CODEC_HDR: + hr = SaveToHDRFile(img[0], pConv->szDest); + break; + +#ifdef USE_OPENEXR + case CODEC_EXR: + hr = SaveToEXRFile(img[0], pConv->szDest); + break; +#endif + + default: + { + WICCodecs codec = (FileType == CODEC_HDP || FileType == CODEC_JXR) ? WIC_CODEC_WMP : static_cast(FileType); + size_t nimages = (dwOptions & (DWORD64(1) << OPT_WIC_MULTIFRAME)) ? nimg : 1; + hr = SaveToWICFile(img, nimages, WIC_FLAGS_NONE, GetWICCodec(codec), pConv->szDest, nullptr, + [&](IPropertyBag2* props) + { + bool wicLossless = (dwOptions & (DWORD64(1) << OPT_WIC_LOSSLESS)) != 0; + + switch (FileType) + { + case WIC_CODEC_JPEG: + if (wicLossless || wicQuality >= 0.f) + { + PROPBAG2 options = {}; + VARIANT varValues = {}; + options.pstrName = const_cast(L"ImageQuality"); + varValues.vt = VT_R4; + varValues.fltVal = (wicLossless) ? 1.f : wicQuality; + (void)props->Write(1, &options, &varValues); + } + break; + + case WIC_CODEC_TIFF: + { + PROPBAG2 options = {}; + VARIANT varValues = {}; + if (wicLossless) + { + options.pstrName = const_cast(L"TiffCompressionMethod"); + varValues.vt = VT_UI1; + varValues.bVal = WICTiffCompressionNone; + } + else if (wicQuality >= 0.f) + { + options.pstrName = const_cast(L"CompressionQuality"); + varValues.vt = VT_R4; + varValues.fltVal = wicQuality; + } + (void)props->Write(1, &options, &varValues); + } + break; + + case WIC_CODEC_WMP: + case CODEC_HDP: + case CODEC_JXR: + { + PROPBAG2 options = {}; + VARIANT varValues = {}; + if (wicLossless) + { + options.pstrName = const_cast(L"Lossless"); + varValues.vt = VT_BOOL; + varValues.bVal = TRUE; + } + else if (wicQuality >= 0.f) + { + options.pstrName = const_cast(L"ImageQuality"); + varValues.vt = VT_R4; + varValues.fltVal = wicQuality; + } + (void)props->Write(1, &options, &varValues); + } + break; + } + }); + } + break; + } + + if (FAILED(hr)) + { + wprintf(L" FAILED (%x)\n", hr); + continue; + } + wprintf(L"\n"); + } + } + + if (nonpow2warn && maxSize <= 4096) + { + // Only emit this warning if ran with -fl set to a 9.x feature level + wprintf(L"\nWARNING: Not all feature levels support non-power-of-2 textures with mipmaps\n"); + } + + if (non4bc) + wprintf(L"\nWARNING: Direct3D requires BC image to be multiple of 4 in width & height\n"); + + if (dwOptions & (DWORD64(1) << OPT_TIMING)) + { + LARGE_INTEGER qpcEnd; + if (QueryPerformanceCounter(&qpcEnd)) + { + LONGLONG delta = qpcEnd.QuadPart - qpcStart.QuadPart; + wprintf(L"\n Processing time: %f seconds\n", double(delta) / double(qpcFreq.QuadPart)); + } + } + + return 0; +} diff --git a/XDKSamples/Tools/xtexconv/xtexconv.sln b/XDKSamples/Tools/xtexconv/xtexconv.sln new file mode 100644 index 0000000000000000000000000000000000000000..28529e4a912884ddd1db6fa58ca1d5961094ca50 --- /dev/null +++ b/XDKSamples/Tools/xtexconv/xtexconv.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtexconv", "xtexconv.vcxproj", "{119CCACE-ACD8-4691-8665-FC78B9CE141D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTex", "..\..\..\Kits\DirectXTex\DirectXTex_XboxOneXDK_PC_2015.vcxproj", "{9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Profile|x64 = Profile|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {119CCACE-ACD8-4691-8665-FC78B9CE141D}.Debug|x64.ActiveCfg = Debug|x64 + {119CCACE-ACD8-4691-8665-FC78B9CE141D}.Debug|x64.Build.0 = Debug|x64 + {119CCACE-ACD8-4691-8665-FC78B9CE141D}.Profile|x64.ActiveCfg = Release|x64 + {119CCACE-ACD8-4691-8665-FC78B9CE141D}.Profile|x64.Build.0 = Release|x64 + {119CCACE-ACD8-4691-8665-FC78B9CE141D}.Release|x64.ActiveCfg = Release|x64 + {119CCACE-ACD8-4691-8665-FC78B9CE141D}.Release|x64.Build.0 = Release|x64 + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}.Debug|x64.ActiveCfg = Debug|x64 + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}.Debug|x64.Build.0 = Debug|x64 + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}.Profile|x64.ActiveCfg = Profile|x64 + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}.Profile|x64.Build.0 = Profile|x64 + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}.Release|x64.ActiveCfg = Release|x64 + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/XDKSamples/Tools/xtexconv/xtexconv.vcxproj b/XDKSamples/Tools/xtexconv/xtexconv.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..9b9b0be978e8f1071a74da89578911e1d653d0e9 --- /dev/null +++ b/XDKSamples/Tools/xtexconv/xtexconv.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {119CCACE-ACD8-4691-8665-FC78B9CE141D} + Win32Proj + xtexconv + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + true + $(XboxOneXDKLatest)PC\include;$(DurangoXDK)PC\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(XboxOneXDKLatest)PC\lib\amd64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + + + false + $(XboxOneXDKLatest)PC\include;$(DurangoXDK)PC\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(XboxOneXDKLatest)PC\lib\amd64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + + + + + + Level4 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\Kits\DirectXTex + Fast + + + Console + true + xg.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + copy "$(XboxOneXDKLatest)bin\xg.dll" "$(TargetDir)xg.dll" + + + Copying XG.DLL + + + $(TargetDir)xg.dll + + + $(XboxOneXDKLatest)bin\xg.dll + + + true + + + + + Level4 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\Kits\DirectXTex + Fast + + + Console + true + true + true + xg.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + copy "$(XboxOneXDKLatest)bin\xg.dll" "$(TargetDir)xg.dll" + + + Copying XG.DLL + + + $(TargetDir)xg.dll + + + $(XboxOneXDKLatest)bin\xg.dll + + + true + + + + + + + + + {9E4D1C18-9E5E-4B35-83BE-74830B9B3C34} + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/XDKSamples/Tools/xtexconv/xtexconv.vcxproj.filters b/XDKSamples/Tools/xtexconv/xtexconv.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..2d4dc667c4266c5b7633a01acf9c2fbbd67c6e0f --- /dev/null +++ b/XDKSamples/Tools/xtexconv/xtexconv.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + + EXR + + + + + + + + + {1135ee12-3af6-47b3-90ed-6f81b9884b1c} + + + + + EXR + + + \ No newline at end of file